Repo created
This commit is contained in:
parent
4af19165ec
commit
68073add76
12458 changed files with 12350765 additions and 2 deletions
370
dev_sandbox/main.mm
Normal file
370
dev_sandbox/main.mm
Normal file
|
|
@ -0,0 +1,370 @@
|
|||
#include "iphone/Maps/Classes/MetalContextFactory.h"
|
||||
|
||||
#include "drape/gl_functions.hpp"
|
||||
#include "drape/oglcontext.hpp"
|
||||
#include "drape/metal/metal_base_context.hpp"
|
||||
#include "drape/vulkan/vulkan_context_factory.hpp"
|
||||
|
||||
#define GLFW_INCLUDE_NONE
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
#if __APPLE__
|
||||
#define GLFW_EXPOSE_NATIVE_COCOA
|
||||
#else
|
||||
#error Unsupported OS
|
||||
#endif
|
||||
#include <GLFW/glfw3native.h>
|
||||
|
||||
#import <AppKit/NSOpenGL.h>
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#import <Metal/Metal.h>
|
||||
#import <QuartzCore/CAMetalLayer.h>
|
||||
|
||||
#include <vulkan/vulkan_macos.h>
|
||||
|
||||
#include <atomic>
|
||||
#include <memory>
|
||||
|
||||
class MacOSVulkanContextFactory : public dp::vulkan::VulkanContextFactory
|
||||
{
|
||||
public:
|
||||
MacOSVulkanContextFactory()
|
||||
: dp::vulkan::VulkanContextFactory(1, 33, false) {}
|
||||
|
||||
void SetSurface(CAMetalLayer *layer)
|
||||
{
|
||||
VkMacOSSurfaceCreateInfoMVK createInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK,
|
||||
.flags = 0,
|
||||
.pView = static_cast<const void *>(CFBridgingRetain(layer)),
|
||||
};
|
||||
|
||||
VkResult statusCode;
|
||||
CHECK(vkCreateMacOSSurfaceMVK, ());
|
||||
statusCode = vkCreateMacOSSurfaceMVK(m_vulkanInstance, &createInfo, nullptr,
|
||||
&m_surface);
|
||||
if (statusCode != VK_SUCCESS)
|
||||
{
|
||||
LOG_ERROR_VK_CALL(vkCreateMacOSSurfaceMVK, statusCode);
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t const renderingQueueIndex = m_drawContext->GetRenderingQueueFamilyIndex();
|
||||
VkBool32 supportsPresent;
|
||||
statusCode = vkGetPhysicalDeviceSurfaceSupportKHR(m_gpu, renderingQueueIndex, m_surface, &supportsPresent);
|
||||
if (statusCode != VK_SUCCESS)
|
||||
{
|
||||
LOG_ERROR_VK_CALL(vkGetPhysicalDeviceSurfaceSupportKHR, statusCode);
|
||||
return;
|
||||
}
|
||||
CHECK_EQUAL(supportsPresent, VK_TRUE, ());
|
||||
|
||||
CHECK(QuerySurfaceSize(), ());
|
||||
|
||||
if (m_drawContext)
|
||||
m_drawContext->SetSurface(m_surface, m_surfaceFormat, m_surfaceCapabilities);
|
||||
}
|
||||
|
||||
void ResetSurface()
|
||||
{
|
||||
if (m_drawContext)
|
||||
m_drawContext->ResetSurface(false);
|
||||
|
||||
vkDestroySurfaceKHR(m_vulkanInstance, m_surface, nullptr);
|
||||
}
|
||||
};
|
||||
|
||||
class MacGLContext : public dp::OGLContext
|
||||
{
|
||||
public:
|
||||
MacGLContext(MacGLContext * contextToShareWith)
|
||||
: m_viewSet(false)
|
||||
{
|
||||
NSOpenGLPixelFormatAttribute attributes[] = {
|
||||
NSOpenGLPFAAccelerated,
|
||||
NSOpenGLPFAOpenGLProfile,
|
||||
NSOpenGLProfileVersion4_1Core,
|
||||
NSOpenGLPFADoubleBuffer,
|
||||
NSOpenGLPFAColorSize,
|
||||
24,
|
||||
NSOpenGLPFAAlphaSize,
|
||||
8,
|
||||
NSOpenGLPFADepthSize,
|
||||
24,
|
||||
NSOpenGLPFAStencilSize,
|
||||
8,
|
||||
0
|
||||
};
|
||||
m_pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:attributes];
|
||||
CHECK(m_pixelFormat, ("Pixel format is not found"));
|
||||
m_context = [[NSOpenGLContext alloc] initWithFormat:m_pixelFormat
|
||||
shareContext:(contextToShareWith ? contextToShareWith->m_context : nil)];
|
||||
int interval = 1;
|
||||
[m_context getValues:&interval forParameter:NSOpenGLContextParameterSwapInterval];
|
||||
}
|
||||
|
||||
~MacGLContext()
|
||||
{
|
||||
@autoreleasepool {
|
||||
[m_context clearDrawable];
|
||||
m_pixelFormat = nil;
|
||||
m_context = nil;
|
||||
}
|
||||
}
|
||||
|
||||
bool BeginRendering() override { return m_viewSet; }
|
||||
|
||||
void Present() override
|
||||
{
|
||||
if (m_viewSet)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_updateSizeMutex);
|
||||
[m_context flushBuffer];
|
||||
}
|
||||
}
|
||||
|
||||
void MakeCurrent() override
|
||||
{
|
||||
[m_context makeCurrentContext];
|
||||
}
|
||||
|
||||
void DoneCurrent() override
|
||||
{
|
||||
[NSOpenGLContext clearCurrentContext];
|
||||
}
|
||||
|
||||
void SetFramebuffer(ref_ptr<dp::BaseFramebuffer> framebuffer) override
|
||||
{
|
||||
if (framebuffer)
|
||||
framebuffer->Bind();
|
||||
else
|
||||
GLFunctions::glBindFramebuffer(0);
|
||||
}
|
||||
|
||||
void SetView(NSView* view)
|
||||
{
|
||||
[m_context setView: view];
|
||||
[m_context update];
|
||||
m_viewSet = true;
|
||||
}
|
||||
|
||||
void UpdateSize(int w, int h)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_updateSizeMutex);
|
||||
[m_context update];
|
||||
}
|
||||
|
||||
private:
|
||||
NSOpenGLPixelFormat * m_pixelFormat = nil;
|
||||
NSOpenGLContext* m_context = nil;
|
||||
std::atomic<bool> m_viewSet;
|
||||
|
||||
std::mutex m_updateSizeMutex;
|
||||
};
|
||||
|
||||
class MacGLContextFactory: public dp::GraphicsContextFactory
|
||||
{
|
||||
public:
|
||||
dp::GraphicsContext * GetDrawContext() override
|
||||
{
|
||||
bool needNotify = false;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_contextAccess);
|
||||
if (m_drawContext == nullptr)
|
||||
{
|
||||
m_drawContext = std::make_unique<MacGLContext>(m_uploadContext.get());
|
||||
needNotify = true;
|
||||
}
|
||||
}
|
||||
if (needNotify)
|
||||
NotifyView();
|
||||
|
||||
std::lock_guard<std::mutex> lock(m_contextAccess);
|
||||
return m_drawContext.get();
|
||||
}
|
||||
|
||||
dp::GraphicsContext * GetResourcesUploadContext() override
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_contextAccess);
|
||||
if (m_uploadContext == nullptr)
|
||||
m_uploadContext = std::make_unique<MacGLContext>(m_drawContext.get());
|
||||
return m_uploadContext.get();
|
||||
}
|
||||
|
||||
void WaitForInitialization(dp::GraphicsContext *) override
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(m_initializationMutex);
|
||||
if (m_isInitialized)
|
||||
return;
|
||||
|
||||
m_initializationCounter++;
|
||||
if (m_initializationCounter >= kGLThreadsCount)
|
||||
{
|
||||
m_isInitialized = true;
|
||||
m_initializationCondition.notify_all();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_initializationCondition.wait(lock, [this] { return m_isInitialized; });
|
||||
}
|
||||
}
|
||||
|
||||
bool IsDrawContextCreated() const override
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_contextAccess);
|
||||
return m_drawContext != nullptr;
|
||||
}
|
||||
|
||||
bool IsUploadContextCreated() const override
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_contextAccess);
|
||||
return m_uploadContext != nullptr;
|
||||
}
|
||||
|
||||
void SetView(NSView* view)
|
||||
{
|
||||
bool needWait;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_contextAccess);
|
||||
needWait = (m_drawContext == nullptr);
|
||||
}
|
||||
if (needWait)
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(m_viewSetMutex);
|
||||
m_viewSetCondition.wait(lock, [this] { return m_viewSet; });
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(m_contextAccess);
|
||||
CHECK(m_drawContext, ());
|
||||
m_drawContext->SetView(view);
|
||||
}
|
||||
|
||||
void UpdateSize(int w, int h)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_contextAccess);
|
||||
if (m_drawContext)
|
||||
m_drawContext->UpdateSize(w, h);
|
||||
}
|
||||
|
||||
private:
|
||||
void NotifyView()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_viewSetMutex);
|
||||
m_viewSet = true;
|
||||
m_viewSetCondition.notify_all();
|
||||
}
|
||||
|
||||
static size_t constexpr kGLThreadsCount = 2;
|
||||
|
||||
std::unique_ptr<MacGLContext> m_drawContext;
|
||||
std::unique_ptr<MacGLContext> m_uploadContext;
|
||||
|
||||
mutable std::mutex m_contextAccess;
|
||||
|
||||
bool m_isInitialized = false;
|
||||
size_t m_initializationCounter = 0;
|
||||
std::condition_variable m_initializationCondition;
|
||||
std::mutex m_initializationMutex;
|
||||
|
||||
bool m_viewSet = false;
|
||||
std::condition_variable m_viewSetCondition;
|
||||
std::mutex m_viewSetMutex;
|
||||
};
|
||||
|
||||
drape_ptr<dp::GraphicsContextFactory> CreateContextFactory(GLFWwindow *window, dp::ApiVersion api, m2::PointU size)
|
||||
{
|
||||
if (api == dp::ApiVersion::Metal)
|
||||
{
|
||||
CAMetalLayer *layer = [CAMetalLayer layer];
|
||||
layer.device = MTLCreateSystemDefaultDevice();
|
||||
layer.opaque = YES;
|
||||
layer.displaySyncEnabled = YES;
|
||||
|
||||
NSWindow *nswindow = glfwGetCocoaWindow(window);
|
||||
NSScreen *screen = [NSScreen mainScreen];
|
||||
CGFloat factor = [screen backingScaleFactor];
|
||||
layer.contentsScale = factor;
|
||||
nswindow.contentView.layer = layer;
|
||||
nswindow.contentView.wantsLayer = YES;
|
||||
|
||||
return make_unique_dp<MetalContextFactory>(layer, size);
|
||||
}
|
||||
|
||||
if (api == dp::ApiVersion::Vulkan)
|
||||
{
|
||||
CAMetalLayer *layer = [CAMetalLayer layer];
|
||||
layer.device = MTLCreateSystemDefaultDevice();
|
||||
layer.opaque = YES;
|
||||
layer.displaySyncEnabled = YES;
|
||||
|
||||
NSWindow *nswindow = glfwGetCocoaWindow(window);
|
||||
NSScreen *screen = [NSScreen mainScreen];
|
||||
CGFloat factor = [screen backingScaleFactor];
|
||||
layer.contentsScale = factor;
|
||||
nswindow.contentView.layer = layer;
|
||||
nswindow.contentView.wantsLayer = YES;
|
||||
|
||||
auto contextFactory = make_unique_dp<MacOSVulkanContextFactory>();
|
||||
contextFactory->SetSurface(layer);
|
||||
return contextFactory;
|
||||
}
|
||||
|
||||
if (api == dp::ApiVersion::OpenGLES3)
|
||||
{
|
||||
NSWindow *nswindow = glfwGetCocoaWindow(window);
|
||||
[nswindow.contentView setWantsBestResolutionOpenGLSurface:YES];
|
||||
return make_unique_dp<MacGLContextFactory>();
|
||||
}
|
||||
|
||||
ASSERT(false, ("API is not available yet"));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void OnCreateDrapeEngine(GLFWwindow *window, dp::ApiVersion api,
|
||||
ref_ptr<dp::GraphicsContextFactory> contextFactory)
|
||||
{
|
||||
if (api == dp::ApiVersion::OpenGLES3)
|
||||
{
|
||||
NSWindow *nswindow = glfwGetCocoaWindow(window);
|
||||
ref_ptr<MacGLContextFactory> macosContextFactory = contextFactory;
|
||||
macosContextFactory->SetView(nswindow.contentView);
|
||||
}
|
||||
}
|
||||
|
||||
void PrepareDestroyContextFactory(ref_ptr<dp::GraphicsContextFactory> contextFactory)
|
||||
{
|
||||
auto const api = contextFactory->GetDrawContext()->GetApiVersion();
|
||||
if (api == dp::ApiVersion::Metal || api == dp::ApiVersion::OpenGLES3)
|
||||
{
|
||||
// Do nothing
|
||||
}
|
||||
else if (api == dp::ApiVersion::Vulkan)
|
||||
{
|
||||
ref_ptr<MacOSVulkanContextFactory> macosContextFactory = contextFactory;
|
||||
macosContextFactory->ResetSurface();
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSERT(false, ("API is not available yet"));
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateContentScale(GLFWwindow *window, float scale)
|
||||
{
|
||||
NSWindow *nswindow = glfwGetCocoaWindow(window);
|
||||
if (nswindow.contentView.layer)
|
||||
nswindow.contentView.layer.contentsScale = scale;
|
||||
}
|
||||
|
||||
void UpdateSize(ref_ptr<dp::GraphicsContextFactory> contextFactory, int w, int h)
|
||||
{
|
||||
if (!contextFactory || !contextFactory->GetDrawContext())
|
||||
return;
|
||||
|
||||
auto const api = contextFactory->GetDrawContext()->GetApiVersion();
|
||||
if (api == dp::ApiVersion::OpenGLES3)
|
||||
{
|
||||
ref_ptr<MacGLContextFactory> macosContextFactory = contextFactory;
|
||||
macosContextFactory->UpdateSize(w, h);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue