diff --git a/.gitmodules b/.gitmodules index 77d1b7e..e74ee9a 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "LogVisor"] path = LogVisor url = https://github.com/AxioDL/LogVisor.git +[submodule "glslang"] + path = glslang + url = https://github.com/AxioDL/glslang.git diff --git a/CMakeLists.txt b/CMakeLists.txt index 514b1e7..47d09c5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,14 +16,16 @@ include_directories(include ${LOG_VISOR_INCLUDE_DIR}) if(NOT GEKKO AND NOT CAFE) list(APPEND PLAT_SRCS lib/graphicsdev/GL.cpp + lib/graphicsdev/Vulkan.cpp lib/graphicsdev/glew.c) list(APPEND PLAT_HDRS - include/boo/graphicsdev/GL.hpp) + include/boo/graphicsdev/GL.hpp + include/boo/graphicsdev/Vulkan.hpp) endif() if(WIN32) - list(APPEND PLAT_SRCS + list(APPEND PLAT_SRCS lib/win/ApplicationWin32.cpp lib/win/WindowWin32.cpp lib/win/Win32Common.hpp @@ -39,7 +41,7 @@ if(WIN32) list(APPEND _BOO_SYS_LIBS Winusb opengl32 Setupapi Imm32) elseif(APPLE) - list(APPEND PLAT_SRCS + list(APPEND PLAT_SRCS lib/mac/ApplicationCocoa.mm lib/mac/WindowCocoa.mm lib/mac/CocoaCommon.hpp @@ -65,7 +67,7 @@ set_source_files_properties(lib/mac/ApplicationCocoa.mm list(APPEND _BOO_SYS_LIBS ${APPKIT_LIBRARY} ${IOKIT_LIBRARY} ${OPENGL_LIBRARY} ${METAL_LIBRARY} ${QUARTZCORE_LIBRARY} ${COREVIDEO_LIBRARY}) else(NOT GEKKO) - list(APPEND PLAT_SRCS + list(APPEND PLAT_SRCS lib/x11/XlibCommon.hpp lib/x11/ApplicationUnix.cpp lib/x11/ApplicationXlib.hpp @@ -130,11 +132,16 @@ if(CMAKE_C_COMPILER_ID STREQUAL "Clang" OR CMAKE_C_COMPILER_ID STREQUAL "AppleCl set_source_files_properties(lib/graphicsdev/glew.c PROPERTIES COMPILE_FLAGS -Os) endif() +add_subdirectory(glslang/glslang EXCLUDE_FROM_ALL) +add_subdirectory(glslang/OGLCompilersDLL EXCLUDE_FROM_ALL) +add_subdirectory(glslang/SPIRV EXCLUDE_FROM_ALL) +list(APPEND _BOO_SYS_LIBS glslang OSDependent OGLCompiler SPIRV) + set(BOO_SYS_LIBS ${_BOO_SYS_LIBS} CACHE PATH "Boo System Libraries" FORCE) set(BOO_SYS_DEFINES ${_BOO_SYS_DEFINES} CACHE PATH "Boo System Defines" FORCE) add_definitions(${_BOO_SYS_DEFINES}) -include_directories(include) +include_directories(include glslang) add_library(Boo lib/inputdev/CafeProPad.cpp include/boo/inputdev/CafeProPad.hpp diff --git a/LICENSE b/LICENSE index 5bec710..b7dd654 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -The AxioDL License +The MIT License Copyright (c) 2015 libBoo Contributors Original Authors: Jack Andersen and Phillip "Antidote" Stephens @@ -13,12 +13,6 @@ furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -Redistributions of the Software may not embed or fetch 3rd-party promotions or -advertising ("adware") that are unrelated to the redistribution's content. -The Software may not be modified to connect to 3rd-party advertising sources -("ad-networks"). Self-promotions of distribution-extensions are permissible -(e.g. microtransactions). - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE diff --git a/glslang b/glslang new file mode 160000 index 0000000..0ea3c3f --- /dev/null +++ b/glslang @@ -0,0 +1 @@ +Subproject commit 0ea3c3f01acf58fefdfc7be3333022b8e84e1997 diff --git a/include/boo/IWindow.hpp b/include/boo/IWindow.hpp index 9a1838e..a83a109 100644 --- a/include/boo/IWindow.hpp +++ b/include/boo/IWindow.hpp @@ -4,6 +4,7 @@ #include "System.hpp" #include #include +#include #undef min #undef max @@ -35,7 +36,7 @@ struct SWindowRect int location[2]; int size[2]; - SWindowRect() {memset(this, 0, sizeof(SWindowRect));} + SWindowRect() {std::memset(this, 0, sizeof(SWindowRect));} SWindowRect(int x, int y, int w, int h) { @@ -240,7 +241,8 @@ enum class EMouseCursor Pointer = 1, HorizontalArrow = 2, VerticalArrow = 3, - IBeam = 4 + IBeam = 4, + Crosshairs = 5 }; enum class EClipboardType diff --git a/include/boo/graphicsdev/GL.hpp b/include/boo/graphicsdev/GL.hpp index 6e43b98..db53875 100644 --- a/include/boo/graphicsdev/GL.hpp +++ b/include/boo/graphicsdev/GL.hpp @@ -1,5 +1,5 @@ -#ifndef GDEV_GLES3_HPP -#define GDEV_GLES3_HPP +#ifndef GDEV_GL_HPP +#define GDEV_GL_HPP #include "IGraphicsDataFactory.hpp" #include "IGraphicsCommandQueue.hpp" @@ -63,4 +63,4 @@ public: } -#endif // GDEV_GLES3_HPP +#endif // GDEV_GL_HPP diff --git a/include/boo/graphicsdev/IGraphicsDataFactory.hpp b/include/boo/graphicsdev/IGraphicsDataFactory.hpp index f944816..5d6eb9a 100644 --- a/include/boo/graphicsdev/IGraphicsDataFactory.hpp +++ b/include/boo/graphicsdev/IGraphicsDataFactory.hpp @@ -184,6 +184,7 @@ struct IGraphicsDataFactory D3D11, D3D12, Metal, + Vulkan, GX, GX2 }; @@ -292,6 +293,7 @@ public: return *this; } ~GraphicsDataToken() {doDestroy();} + operator bool() const {return m_factory && m_data;} }; } diff --git a/include/boo/graphicsdev/Vulkan.hpp b/include/boo/graphicsdev/Vulkan.hpp new file mode 100644 index 0000000..b57789b --- /dev/null +++ b/include/boo/graphicsdev/Vulkan.hpp @@ -0,0 +1,82 @@ +#ifndef GDEV_VULKAN_HPP +#define GDEV_VULKAN_HPP + +#include "IGraphicsDataFactory.hpp" +#include "IGraphicsCommandQueue.hpp" +#include "boo/IGraphicsContext.hpp" +#include +#include +#include + +namespace boo +{ + +class VulkanDataFactory : public IGraphicsDataFactory +{ + friend struct VulkanCommandQueue; + IGraphicsContext* m_parent; + static ThreadLocalPtr m_deferredData; + std::unordered_set m_committedData; + std::mutex m_committedMutex; + std::vector m_texUnis; + void destroyData(IGraphicsData*); + void destroyAllData(); +public: + VulkanDataFactory(IGraphicsContext* parent); + ~VulkanDataFactory() {destroyAllData();} + + Platform platform() const {return Platform::Vulkan;} + const SystemChar* platformName() const {return _S("Vulkan");} + + IGraphicsBufferS* newStaticBuffer(BufferUse use, const void* data, size_t stride, size_t count); + IGraphicsBufferS* newStaticBuffer(BufferUse use, std::unique_ptr&& data, size_t stride, size_t count); + IGraphicsBufferD* newDynamicBuffer(BufferUse use, size_t stride, size_t count); + + ITextureS* newStaticTexture(size_t width, size_t height, size_t mips, TextureFormat fmt, + const void* data, size_t sz); + ITextureS* newStaticTexture(size_t width, size_t height, size_t mips, TextureFormat fmt, + std::unique_ptr&& data, size_t sz); + ITextureSA* newStaticArrayTexture(size_t width, size_t height, size_t layers, TextureFormat fmt, + const void* data, size_t sz); + ITextureD* newDynamicTexture(size_t width, size_t height, TextureFormat fmt); + ITextureR* newRenderTexture(size_t width, size_t height, size_t samples); + + bool bindingNeedsVertexFormat() const {return true;} + IVertexFormat* newVertexFormat(size_t elementCount, const VertexElementDescriptor* elements); + + IShaderPipeline* newShaderPipeline(const char* vertSource, const char* fragSource, + std::vector& vertBlobOut, std::vector& fragBlobOut, + std::vector& pipelineBlob, + size_t texCount, const char* texArrayName, + size_t uniformBlockCount, const char** uniformBlockNames, + BlendFactor srcFac, BlendFactor dstFac, + bool depthTest, bool depthWrite, bool backfaceCulling); + + IShaderPipeline* newShaderPipeline(const char* vertSource, const char* fragSource, + size_t texCount, const char* texArrayName, + size_t uniformBlockCount, const char** uniformBlockNames, + BlendFactor srcFac, BlendFactor dstFac, + bool depthTest, bool depthWrite, bool backfaceCulling) + { + std::vector vertBlob; + std::vector fragBlob; + std::vector pipelineBlob; + return newShaderPipeline(vertSource, fragSource, vertBlob, fragBlob, pipelineBlob, + texCount, texArrayName, uniformBlockCount, uniformBlockNames, + srcFac, dstFac, depthTest, depthWrite, backfaceCulling); + } + + IShaderDataBinding* + newShaderDataBinding(IShaderPipeline* pipeline, + IVertexFormat* vtxFormat, + IGraphicsBuffer* vbo, IGraphicsBuffer* instVbo, IGraphicsBuffer* ibo, + size_t ubufCount, IGraphicsBuffer** ubufs, + size_t texCount, ITexture** texs); + + void reset(); + GraphicsDataToken commit(); +}; + +} + +#endif // GDEV_VULKAN_HPP diff --git a/include/boo/graphicsdev/glxew.h b/include/boo/graphicsdev/glxew.h index a30f666..c477532 100644 --- a/include/boo/graphicsdev/glxew.h +++ b/include/boo/graphicsdev/glxew.h @@ -98,7 +98,7 @@ #include #include #include -#include +#include "glew.h" #ifdef __cplusplus extern "C" { diff --git a/lib/graphicsdev/GL.cpp b/lib/graphicsdev/GL.cpp index e193bc4..8d8de7f 100644 --- a/lib/graphicsdev/GL.cpp +++ b/lib/graphicsdev/GL.cpp @@ -66,16 +66,20 @@ class GLGraphicsBufferD : public IGraphicsBufferD { friend class GLDataFactory; friend struct GLCommandQueue; - struct GLCommandQueue* m_q; GLuint m_bufs[3]; GLenum m_target; std::unique_ptr m_cpuBuf; size_t m_cpuSz = 0; int m_validMask = 0; - GLGraphicsBufferD(GLCommandQueue* q, BufferUse use, size_t sz) - : m_q(q), m_target(USE_TABLE[int(use)]), m_cpuBuf(new uint8_t[sz]), m_cpuSz(sz) + GLGraphicsBufferD(BufferUse use, size_t sz) + : m_target(USE_TABLE[int(use)]), m_cpuBuf(new uint8_t[sz]), m_cpuSz(sz) { glGenBuffers(3, m_bufs); + for (int i=0 ; i<3 ; ++i) + { + glBindBuffer(m_target, m_bufs[i]); + glBufferData(m_target, m_cpuSz, nullptr, GL_STREAM_DRAW); + } } void update(int b); public: @@ -193,7 +197,6 @@ class GLTextureD : public ITextureD { friend class GLDataFactory; friend struct GLCommandQueue; - struct GLCommandQueue* m_q; GLuint m_texs[3]; std::unique_ptr m_cpuBuf; size_t m_cpuSz = 0; @@ -201,7 +204,7 @@ class GLTextureD : public ITextureD size_t m_width = 0; size_t m_height = 0; int m_validMask = 0; - GLTextureD(GLCommandQueue* q, size_t width, size_t height, TextureFormat fmt); + GLTextureD(size_t width, size_t height, TextureFormat fmt); void update(int b); public: ~GLTextureD(); @@ -223,6 +226,7 @@ class GLTextureR : public ITextureR size_t m_width = 0; size_t m_height = 0; size_t m_samples = 0; + GLenum m_target; GLTextureR(GLCommandQueue* q, size_t width, size_t height, size_t samples); public: ~GLTextureR(); @@ -230,17 +234,28 @@ public: void bind(size_t idx) const { glActiveTexture(GL_TEXTURE0 + idx); - glBindTexture(GL_TEXTURE_2D, m_texs[0]); + glBindTexture(m_target, m_texs[0]); } void resize(size_t width, size_t height) { m_width = width; m_height = height; - glBindTexture(GL_TEXTURE_2D, m_texs[0]); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); - glBindTexture(GL_TEXTURE_2D, m_texs[1]); - glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, width, height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, nullptr); + + if (m_samples > 1) + { + glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, m_texs[0]); + glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, m_samples, GL_RGBA, width, height, GL_FALSE); + glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, m_texs[1]); + glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, m_samples, GL_DEPTH_COMPONENT24, width, height, GL_FALSE); + } + else + { + glBindTexture(GL_TEXTURE_2D, m_texs[0]); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); + glBindTexture(GL_TEXTURE_2D, m_texs[1]); + glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, width, height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, nullptr); + } } }; @@ -1142,7 +1157,7 @@ void GLGraphicsBufferD::update(int b) if ((slot & m_validMask) == 0) { glBindBuffer(m_target, m_bufs[b]); - glBufferData(m_target, m_cpuSz, m_cpuBuf.get(), GL_DYNAMIC_DRAW); + glBufferSubData(m_target, 0, m_cpuSz, m_cpuBuf.get()); m_validMask |= slot; } } @@ -1173,18 +1188,17 @@ void GLGraphicsBufferD::bindUniform(size_t idx, int b) IGraphicsBufferD* GLDataFactory::newDynamicBuffer(BufferUse use, size_t stride, size_t count) { - GLCommandQueue* q = static_cast(m_parent->getCommandQueue()); - GLGraphicsBufferD* retval = new GLGraphicsBufferD(q, use, stride * count); + GLGraphicsBufferD* retval = new GLGraphicsBufferD(use, stride * count); if (!m_deferredData.get()) m_deferredData.reset(new struct GLData()); m_deferredData->m_DBufs.emplace_back(retval); return retval; } -GLTextureD::GLTextureD(GLCommandQueue* q, size_t width, size_t height, TextureFormat fmt) -: m_q(q), m_width(width), m_height(height) +GLTextureD::GLTextureD(size_t width, size_t height, TextureFormat fmt) +: m_width(width), m_height(height) { - int pxPitch; + int pxPitch = 4; switch (fmt) { case TextureFormat::RGBA8: @@ -1250,8 +1264,7 @@ void GLTextureD::bind(size_t idx, int b) ITextureD* GLDataFactory::newDynamicTexture(size_t width, size_t height, TextureFormat fmt) { - GLCommandQueue* q = static_cast(m_parent->getCommandQueue()); - GLTextureD* retval = new GLTextureD(q, width, height, fmt); + GLTextureD* retval = new GLTextureD(width, height, fmt); if (!m_deferredData.get()) m_deferredData.reset(new struct GLData()); m_deferredData->m_DTexs.emplace_back(retval); @@ -1262,10 +1275,22 @@ GLTextureR::GLTextureR(GLCommandQueue* q, size_t width, size_t height, size_t sa : m_q(q), m_width(width), m_height(height), m_samples(samples) { glGenTextures(2, m_texs); - glBindTexture(GL_TEXTURE_2D, m_texs[0]); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); - glBindTexture(GL_TEXTURE_2D, m_texs[1]); - glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, width, height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, nullptr); + if (samples > 1) + { + m_target = GL_TEXTURE_2D_MULTISAMPLE; + glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, m_texs[0]); + glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, samples, GL_RGBA, width, height, GL_FALSE); + glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, m_texs[1]); + glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, samples, GL_DEPTH_COMPONENT24, width, height, GL_FALSE); + } + else + { + m_target = GL_TEXTURE_2D; + glBindTexture(GL_TEXTURE_2D, m_texs[0]); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); + glBindTexture(GL_TEXTURE_2D, m_texs[1]); + glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, width, height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, nullptr); + } m_q->addFBO(this); } GLTextureR::~GLTextureR() {glDeleteTextures(2, m_texs); m_q->delFBO(this);} diff --git a/lib/graphicsdev/Metal.mm b/lib/graphicsdev/Metal.mm index 148b264..c46a85e 100644 --- a/lib/graphicsdev/Metal.mm +++ b/lib/graphicsdev/Metal.mm @@ -41,13 +41,13 @@ class MetalGraphicsBufferS : public IGraphicsBufferS MetalGraphicsBufferS(BufferUse use, MetalContext* ctx, const void* data, size_t stride, size_t count) : m_stride(stride), m_count(count), m_sz(stride * count) { - m_buf = [ctx->m_dev.get() newBufferWithBytes:data length:m_sz options:MTL_STATIC]; + m_buf = [ctx->m_dev newBufferWithBytes:data length:m_sz options:MTL_STATIC]; } public: size_t m_stride; size_t m_count; size_t m_sz; - NSPtr> m_buf; + id m_buf; ~MetalGraphicsBufferS() = default; }; @@ -62,15 +62,15 @@ class MetalGraphicsBufferD : public IGraphicsBufferD : m_q(q), m_stride(stride), m_count(count), m_sz(stride * count) { m_cpuBuf.reset(new uint8_t[m_sz]); - m_bufs[0] = [ctx->m_dev.get() newBufferWithLength:m_sz options:MTL_DYNAMIC]; - m_bufs[1] = [ctx->m_dev.get() newBufferWithLength:m_sz options:MTL_DYNAMIC]; + m_bufs[0] = [ctx->m_dev newBufferWithLength:m_sz options:MTL_DYNAMIC]; + m_bufs[1] = [ctx->m_dev newBufferWithLength:m_sz options:MTL_DYNAMIC]; } void update(int b); public: size_t m_stride; size_t m_count; size_t m_sz; - NSPtr> m_bufs[2]; + id m_bufs[2]; MetalGraphicsBufferD() = default; void load(const void* data, size_t sz); @@ -95,30 +95,30 @@ class MetalTextureS : public ITextureS default: break; } - NSPtr desc; @autoreleasepool { - desc = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:pfmt - width:width height:height - mipmapped:(mips>1)?YES:NO]; - } - desc.get().usage = MTLTextureUsageShaderRead; - desc.get().mipmapLevelCount = mips; - m_tex = [ctx->m_dev.get() newTextureWithDescriptor:desc.get()]; - const uint8_t* dataIt = reinterpret_cast(data); - for (size_t i=0 ; i1)?YES:NO]; + desc.usage = MTLTextureUsageShaderRead; + desc.mipmapLevelCount = mips; + m_tex = [ctx->m_dev newTextureWithDescriptor:desc]; + const uint8_t* dataIt = reinterpret_cast(data); + for (size_t i=0 ; i> m_tex; + id m_tex; ~MetalTextureS() = default; }; @@ -139,31 +139,31 @@ class MetalTextureSA : public ITextureSA default: break; } - NSPtr desc; @autoreleasepool { - desc = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:pfmt - width:width height:height - mipmapped:NO]; - } - desc.get().textureType = MTLTextureType2DArray; - desc.get().arrayLength = layers; - desc.get().usage = MTLTextureUsageShaderRead; - m_tex = [ctx->m_dev.get() newTextureWithDescriptor:desc.get()]; - const uint8_t* dataIt = reinterpret_cast(data); - for (size_t i=0 ; im_dev newTextureWithDescriptor:desc]; + const uint8_t* dataIt = reinterpret_cast(data); + for (size_t i=0 ; i> m_tex; + id m_tex; ~MetalTextureSA() = default; }; @@ -199,20 +199,20 @@ class MetalTextureD : public ITextureD m_cpuSz = width * height * m_pxPitch; m_cpuBuf.reset(new uint8_t[m_cpuSz]); - NSPtr desc; @autoreleasepool { - desc = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:format - width:width height:height - mipmapped:NO]; + MTLTextureDescriptor* desc = + [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:format + width:width height:height + mipmapped:NO]; + desc.usage = MTLTextureUsageShaderRead; + m_texs[0] = [ctx->m_dev newTextureWithDescriptor:desc]; + m_texs[1] = [ctx->m_dev newTextureWithDescriptor:desc]; } - desc.get().usage = MTLTextureUsageShaderRead; - m_texs[0] = [ctx->m_dev.get() newTextureWithDescriptor:desc.get()]; - m_texs[1] = [ctx->m_dev.get() newTextureWithDescriptor:desc.get()]; } void update(int b); public: - NSPtr> m_texs[2]; + id m_texs[2]; ~MetalTextureD() = default; void load(const void* data, size_t sz); @@ -230,49 +230,49 @@ class MetalTextureR : public ITextureR void Setup(MetalContext* ctx, size_t width, size_t height, size_t samples) { - NSPtr desc; @autoreleasepool { - desc = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatBGRA8Unorm - width:width height:height - mipmapped:NO]; + MTLTextureDescriptor* desc = + [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatBGRA8Unorm + width:width height:height + mipmapped:NO]; m_passDesc = [MTLRenderPassDescriptor renderPassDescriptor]; - } - desc.get().usage = MTLTextureUsageRenderTarget | MTLTextureUsageShaderRead; - desc.get().storageMode = MTLStorageModePrivate; + desc.usage = MTLTextureUsageRenderTarget | MTLTextureUsageShaderRead; + desc.storageMode = MTLStorageModePrivate; - m_tex = [ctx->m_dev.get() newTextureWithDescriptor:desc.get()]; - - if (samples > 1) - { - desc.get().textureType = MTLTextureType2DMultisample; - desc.get().sampleCount = samples; - m_msaaTex = [ctx->m_dev.get() newTextureWithDescriptor:desc.get()]; - - desc.get().pixelFormat = MTLPixelFormatDepth32Float; - m_depthTex = [ctx->m_dev.get() newTextureWithDescriptor:desc.get()]; - - m_passDesc.get().colorAttachments[0].texture = m_msaaTex.get(); - m_passDesc.get().colorAttachments[0].resolveTexture = m_tex.get(); - m_passDesc.get().colorAttachments[0].loadAction = MTLLoadActionClear; - m_passDesc.get().colorAttachments[0].storeAction = MTLStoreActionMultisampleResolve; - - m_passDesc.get().depthAttachment.texture = m_depthTex.get(); - m_passDesc.get().depthAttachment.loadAction = MTLLoadActionClear; - m_passDesc.get().depthAttachment.storeAction = MTLStoreActionDontCare; - } - else - { - desc.get().pixelFormat = MTLPixelFormatDepth32Float; - m_depthTex = [ctx->m_dev.get() newTextureWithDescriptor:desc.get()]; - - m_passDesc.get().colorAttachments[0].texture = m_tex.get(); - m_passDesc.get().colorAttachments[0].loadAction = MTLLoadActionClear; - m_passDesc.get().colorAttachments[0].storeAction = MTLStoreActionStore; - - m_passDesc.get().depthAttachment.texture = m_depthTex.get(); - m_passDesc.get().depthAttachment.loadAction = MTLLoadActionClear; - m_passDesc.get().depthAttachment.storeAction = MTLStoreActionDontCare; + m_tex = [ctx->m_dev newTextureWithDescriptor:desc]; + + if (samples > 1) + { + desc.textureType = MTLTextureType2DMultisample; + desc.sampleCount = samples; + m_msaaTex = [ctx->m_dev newTextureWithDescriptor:desc]; + + desc.pixelFormat = MTLPixelFormatDepth32Float; + m_depthTex = [ctx->m_dev newTextureWithDescriptor:desc]; + + m_passDesc.colorAttachments[0].texture = m_msaaTex; + m_passDesc.colorAttachments[0].resolveTexture = m_tex; + m_passDesc.colorAttachments[0].loadAction = MTLLoadActionClear; + m_passDesc.colorAttachments[0].storeAction = MTLStoreActionMultisampleResolve; + + m_passDesc.depthAttachment.texture = m_depthTex; + m_passDesc.depthAttachment.loadAction = MTLLoadActionClear; + m_passDesc.depthAttachment.storeAction = MTLStoreActionDontCare; + } + else + { + desc.pixelFormat = MTLPixelFormatDepth32Float; + m_depthTex = [ctx->m_dev newTextureWithDescriptor:desc]; + + m_passDesc.colorAttachments[0].texture = m_tex; + m_passDesc.colorAttachments[0].loadAction = MTLLoadActionClear; + m_passDesc.colorAttachments[0].storeAction = MTLStoreActionStore; + + m_passDesc.depthAttachment.texture = m_depthTex; + m_passDesc.depthAttachment.loadAction = MTLLoadActionClear; + m_passDesc.depthAttachment.storeAction = MTLStoreActionDontCare; + } } } @@ -284,10 +284,10 @@ class MetalTextureR : public ITextureR } public: size_t samples() const {return m_samples;} - NSPtr> m_tex; - NSPtr> m_msaaTex; - NSPtr> m_depthTex; - NSPtr m_passDesc; + id m_tex; + id m_msaaTex; + id m_depthTex; + MTLRenderPassDescriptor* m_passDesc; ~MetalTextureR() = default; void resize(MetalContext* ctx, size_t width, size_t height) @@ -301,7 +301,7 @@ public: Setup(ctx, width, height, m_samples); } - id getRenderColorRes() {if (m_samples > 1) return m_msaaTex.get(); return m_tex.get();} + id getRenderColorRes() {if (m_samples > 1) return m_msaaTex; return m_tex;} }; static const size_t SEMANTIC_SIZE_TABLE[] = @@ -337,7 +337,7 @@ static const MTLVertexFormat SEMANTIC_TYPE_TABLE[] = struct MetalVertexFormat : IVertexFormat { size_t m_elementCount; - NSPtr m_vdesc; + MTLVertexDescriptor* m_vdesc; MetalVertexFormat(size_t elementCount, const VertexElementDescriptor* elements) : m_elementCount(elementCount) { @@ -354,12 +354,12 @@ struct MetalVertexFormat : IVertexFormat } m_vdesc = [MTLVertexDescriptor vertexDescriptor]; - MTLVertexBufferLayoutDescriptor* layoutDesc = m_vdesc.get().layouts[0]; + MTLVertexBufferLayoutDescriptor* layoutDesc = m_vdesc.layouts[0]; layoutDesc.stride = stride; layoutDesc.stepFunction = MTLVertexStepFunctionPerVertex; layoutDesc.stepRate = 1; - layoutDesc = m_vdesc.get().layouts[1]; + layoutDesc = m_vdesc.layouts[1]; layoutDesc.stride = instStride; layoutDesc.stepFunction = MTLVertexStepFunctionPerInstance; layoutDesc.stepRate = 1; @@ -369,7 +369,7 @@ struct MetalVertexFormat : IVertexFormat for (size_t i=0 ; isemantic & VertexSemantic::SemanticMask); if ((elemin->semantic & VertexSemantic::Instanced) != VertexSemantic::None) { @@ -415,40 +415,40 @@ class MetalShaderPipeline : public IShaderPipeline if (backfaceCulling) m_cullMode = MTLCullModeBack; - NSPtr desc = [MTLRenderPipelineDescriptor new]; - desc.get().vertexFunction = vert; - desc.get().fragmentFunction = frag; - desc.get().vertexDescriptor = vtxFmt->m_vdesc.get(); - desc.get().sampleCount = targetSamples; - desc.get().colorAttachments[0].pixelFormat = MTLPixelFormatBGRA8Unorm; - desc.get().colorAttachments[0].blendingEnabled = dstFac != BlendFactor::Zero; - desc.get().colorAttachments[0].sourceRGBBlendFactor = BLEND_FACTOR_TABLE[int(srcFac)]; - desc.get().colorAttachments[0].destinationRGBBlendFactor = BLEND_FACTOR_TABLE[int(dstFac)]; - desc.get().depthAttachmentPixelFormat = MTLPixelFormatDepth32Float; - desc.get().inputPrimitiveTopology = MTLPrimitiveTopologyClassTriangle; + MTLRenderPipelineDescriptor* desc = [MTLRenderPipelineDescriptor new]; + desc.vertexFunction = vert; + desc.fragmentFunction = frag; + desc.vertexDescriptor = vtxFmt->m_vdesc; + desc.sampleCount = targetSamples; + desc.colorAttachments[0].pixelFormat = MTLPixelFormatBGRA8Unorm; + desc.colorAttachments[0].blendingEnabled = dstFac != BlendFactor::Zero; + desc.colorAttachments[0].sourceRGBBlendFactor = BLEND_FACTOR_TABLE[int(srcFac)]; + desc.colorAttachments[0].destinationRGBBlendFactor = BLEND_FACTOR_TABLE[int(dstFac)]; + desc.depthAttachmentPixelFormat = MTLPixelFormatDepth32Float; + desc.inputPrimitiveTopology = MTLPrimitiveTopologyClassTriangle; NSError* err = nullptr; - m_state = [ctx->m_dev.get() newRenderPipelineStateWithDescriptor:desc.get() error:&err]; + m_state = [ctx->m_dev newRenderPipelineStateWithDescriptor:desc error:&err]; if (err) Log.report(LogVisor::FatalError, "error making shader pipeline: %s", [[err localizedDescription] UTF8String]); - NSPtr dsDesc = [MTLDepthStencilDescriptor new]; + MTLDepthStencilDescriptor* dsDesc = [MTLDepthStencilDescriptor new]; if (depthTest) - dsDesc.get().depthCompareFunction = MTLCompareFunctionLessEqual; - dsDesc.get().depthWriteEnabled = depthWrite; - m_dsState = [ctx->m_dev.get() newDepthStencilStateWithDescriptor:dsDesc.get()]; + dsDesc.depthCompareFunction = MTLCompareFunctionLessEqual; + dsDesc.depthWriteEnabled = depthWrite; + m_dsState = [ctx->m_dev newDepthStencilStateWithDescriptor:dsDesc]; } public: - NSPtr> m_state; - NSPtr> m_dsState; + id m_state; + id m_dsState; ~MetalShaderPipeline() = default; MetalShaderPipeline& operator=(const MetalShaderPipeline&) = delete; MetalShaderPipeline(const MetalShaderPipeline&) = delete; void bind(id enc) { - [enc setRenderPipelineState:m_state.get()]; - [enc setDepthStencilState:m_dsState.get()]; + [enc setRenderPipelineState:m_state]; + [enc setDepthStencilState:m_dsState]; [enc setCullMode:m_cullMode]; } }; @@ -458,12 +458,12 @@ static id GetBufferGPUResource(const IGraphicsBuffer* buf, int idx) if (buf->dynamic()) { const MetalGraphicsBufferD* cbuf = static_cast(buf); - return cbuf->m_bufs[idx].get(); + return cbuf->m_bufs[idx]; } else { const MetalGraphicsBufferS* cbuf = static_cast(buf); - return cbuf->m_buf.get(); + return cbuf->m_buf; } } @@ -474,22 +474,22 @@ static id GetTextureGPUResource(const ITexture* tex, int idx) case TextureType::Dynamic: { const MetalTextureD* ctex = static_cast(tex); - return ctex->m_texs[idx].get(); + return ctex->m_texs[idx]; } case TextureType::Static: { const MetalTextureS* ctex = static_cast(tex); - return ctex->m_tex.get(); + return ctex->m_tex; } case TextureType::StaticArray: { const MetalTextureSA* ctex = static_cast(tex); - return ctex->m_tex.get(); + return ctex->m_tex; } case TextureType::Render: { const MetalTextureR* ctex = static_cast(tex); - return ctex->m_tex.get(); + return ctex->m_tex; } default: break; } @@ -547,8 +547,8 @@ struct MetalCommandQueue : IGraphicsCommandQueue MetalContext* m_ctx; IWindow* m_parentWindow; IGraphicsContext* m_parent; - NSPtr> m_cmdBuf; - NSPtr> m_enc; + id m_cmdBuf; + id m_enc; bool m_running = true; size_t m_fillBuf = 0; @@ -559,7 +559,7 @@ struct MetalCommandQueue : IGraphicsCommandQueue { @autoreleasepool { - m_cmdBuf = [ctx->m_q.get() commandBuffer]; + m_cmdBuf = [ctx->m_q commandBuffer]; } } @@ -567,7 +567,7 @@ struct MetalCommandQueue : IGraphicsCommandQueue { m_running = false; if (m_inProgress) - [m_cmdBuf.get() waitUntilCompleted]; + [m_cmdBuf waitUntilCompleted]; } ~MetalCommandQueue() @@ -579,7 +579,7 @@ struct MetalCommandQueue : IGraphicsCommandQueue void setShaderDataBinding(IShaderDataBinding* binding) { MetalShaderDataBinding* cbind = static_cast(binding); - cbind->bind(m_enc.get(), m_fillBuf); + cbind->bind(m_enc, m_fillBuf); m_boundData = cbind; } @@ -587,10 +587,10 @@ struct MetalCommandQueue : IGraphicsCommandQueue void setRenderTarget(ITextureR* target) { MetalTextureR* ctarget = static_cast(target); - [m_enc.get() endEncoding]; + [m_enc endEncoding]; @autoreleasepool { - m_enc = [m_cmdBuf.get() renderCommandEncoderWithDescriptor:ctarget->m_passDesc.get()]; + m_enc = [m_cmdBuf renderCommandEncoderWithDescriptor:ctarget->m_passDesc]; } m_boundTarget = ctarget; } @@ -599,7 +599,7 @@ struct MetalCommandQueue : IGraphicsCommandQueue { MTLViewport vp = {double(rect.location[0]), double(rect.location[1]), double(rect.size[0]), double(rect.size[1]), 0.0, 1.0}; - [m_enc.get() setViewport:vp]; + [m_enc setViewport:vp]; } void setScissor(const SWindowRect& rect) @@ -609,7 +609,7 @@ struct MetalCommandQueue : IGraphicsCommandQueue MTLScissorRect scissor = {NSUInteger(rect.location[0]), NSUInteger(m_boundTarget->m_height - rect.location[1] - rect.size[1]), NSUInteger(rect.size[0]), NSUInteger(rect.size[1])}; - [m_enc.get() setScissorRect:scissor]; + [m_enc setScissorRect:scissor]; } } @@ -654,31 +654,31 @@ struct MetalCommandQueue : IGraphicsCommandQueue void draw(size_t start, size_t count) { - [m_enc.get() drawPrimitives:m_primType vertexStart:start vertexCount:count]; + [m_enc drawPrimitives:m_primType vertexStart:start vertexCount:count]; } void drawIndexed(size_t start, size_t count) { - [m_enc.get() drawIndexedPrimitives:m_primType - indexCount:count - indexType:MTLIndexTypeUInt32 - indexBuffer:GetBufferGPUResource(m_boundData->m_ibuf, m_fillBuf) - indexBufferOffset:start*4]; + [m_enc drawIndexedPrimitives:m_primType + indexCount:count + indexType:MTLIndexTypeUInt32 + indexBuffer:GetBufferGPUResource(m_boundData->m_ibuf, m_fillBuf) + indexBufferOffset:start*4]; } void drawInstances(size_t start, size_t count, size_t instCount) { - [m_enc.get() drawPrimitives:m_primType vertexStart:start vertexCount:count instanceCount:instCount]; + [m_enc drawPrimitives:m_primType vertexStart:start vertexCount:count instanceCount:instCount]; } void drawInstancesIndexed(size_t start, size_t count, size_t instCount) { - [m_enc.get() drawIndexedPrimitives:m_primType - indexCount:count - indexType:MTLIndexTypeUInt32 - indexBuffer:GetBufferGPUResource(m_boundData->m_ibuf, m_fillBuf) - indexBufferOffset:start*4 - instanceCount:instCount]; + [m_enc drawIndexedPrimitives:m_primType + indexCount:count + indexType:MTLIndexTypeUInt32 + indexBuffer:GetBufferGPUResource(m_boundData->m_ibuf, m_fillBuf) + indexBufferOffset:start*4 + instanceCount:instCount]; } MetalTextureR* m_needsDisplay = nullptr; @@ -707,13 +707,13 @@ struct MetalCommandQueue : IGraphicsCommandQueue @autoreleasepool { - [m_enc.get() endEncoding]; - m_enc.reset(); + [m_enc endEncoding]; + m_enc = nullptr; /* Abandon if in progress (renderer too slow) */ if (m_inProgress) { - m_cmdBuf = [m_ctx->m_q.get() commandBuffer]; + m_cmdBuf = [m_ctx->m_q commandBuffer]; return; } @@ -723,7 +723,7 @@ struct MetalCommandQueue : IGraphicsCommandQueue for (const auto& resize : m_texResizes) resize.first->resize(m_ctx, resize.second.first, resize.second.second); m_texResizes.clear(); - m_cmdBuf = [m_ctx->m_q.get() commandBuffer]; + m_cmdBuf = [m_ctx->m_q commandBuffer]; return; } @@ -747,11 +747,11 @@ struct MetalCommandQueue : IGraphicsCommandQueue if (drawable) { id dest = drawable.texture; - if (m_needsDisplay->m_tex.get().width == dest.width && - m_needsDisplay->m_tex.get().height == dest.height) + if (m_needsDisplay->m_tex.width == dest.width && + m_needsDisplay->m_tex.height == dest.height) { - id blitEnc = [m_cmdBuf.get() blitCommandEncoder]; - [blitEnc copyFromTexture:m_needsDisplay->m_tex.get() + id blitEnc = [m_cmdBuf blitCommandEncoder]; + [blitEnc copyFromTexture:m_needsDisplay->m_tex sourceSlice:0 sourceLevel:0 sourceOrigin:MTLOriginMake(0, 0, 0) @@ -761,7 +761,7 @@ struct MetalCommandQueue : IGraphicsCommandQueue destinationLevel:0 destinationOrigin:MTLOriginMake(0, 0, 0)]; [blitEnc endEncoding]; - [m_cmdBuf.get() presentDrawable:drawable]; + [m_cmdBuf presentDrawable:drawable]; } } } @@ -771,10 +771,10 @@ struct MetalCommandQueue : IGraphicsCommandQueue m_drawBuf = m_fillBuf; m_fillBuf ^= 1; - [m_cmdBuf.get() addCompletedHandler:^(id buf) {m_inProgress = false;}]; + [m_cmdBuf addCompletedHandler:^(id buf) {m_inProgress = false;}]; m_inProgress = true; - [m_cmdBuf.get() commit]; - m_cmdBuf = [m_ctx->m_q.get() commandBuffer]; + [m_cmdBuf commit]; + m_cmdBuf = [m_ctx->m_q commandBuffer]; } } }; @@ -784,7 +784,7 @@ void MetalGraphicsBufferD::update(int b) int slot = 1 << b; if ((slot & m_validSlots) == 0) { - id res = m_bufs[b].get(); + id res = m_bufs[b]; memcpy(res.contents, m_cpuBuf.get(), m_sz); m_validSlots |= slot; } @@ -811,7 +811,7 @@ void MetalTextureD::update(int b) int slot = 1 << b; if ((slot & m_validSlots) == 0) { - id res = m_texs[b].get(); + id res = m_texs[b]; [res replaceRegion:MTLRegionMake2D(0, 0, m_width, m_height) mipmapLevel:0 withBytes:m_cpuBuf.get() bytesPerRow:m_width*m_pxPitch]; m_validSlots |= slot; @@ -924,25 +924,25 @@ IShaderPipeline* MetalDataFactory::newShaderPipeline(const char* vertSource, con BlendFactor srcFac, BlendFactor dstFac, bool depthTest, bool depthWrite, bool backfaceCulling) { - NSPtr compOpts = [MTLCompileOptions new]; - compOpts.get().languageVersion = MTLLanguageVersion1_1; + MTLCompileOptions* compOpts = [MTLCompileOptions new]; + compOpts.languageVersion = MTLLanguageVersion1_1; NSError* err = nullptr; - NSPtr> vertShaderLib = [m_ctx->m_dev.get() newLibraryWithSource:@(vertSource) - options:compOpts.get() - error:&err]; + id vertShaderLib = [m_ctx->m_dev newLibraryWithSource:@(vertSource) + options:compOpts + error:&err]; if (err) Log.report(LogVisor::FatalError, "error compiling vert shader: %s", [[err localizedDescription] UTF8String]); - NSPtr> vertFunc = [vertShaderLib.get() newFunctionWithName:@"vmain"]; + id vertFunc = [vertShaderLib newFunctionWithName:@"vmain"]; - NSPtr> fragShaderLib = [m_ctx->m_dev.get() newLibraryWithSource:@(fragSource) - options:compOpts.get() - error:&err]; + id fragShaderLib = [m_ctx->m_dev newLibraryWithSource:@(fragSource) + options:compOpts + error:&err]; if (err) Log.report(LogVisor::FatalError, "error compiling frag shader: %s", [[err localizedDescription] UTF8String]); - NSPtr> fragFunc = [fragShaderLib.get() newFunctionWithName:@"fmain"]; + id fragFunc = [fragShaderLib newFunctionWithName:@"fmain"]; - MetalShaderPipeline* retval = new MetalShaderPipeline(m_ctx, vertFunc.get(), fragFunc.get(), + MetalShaderPipeline* retval = new MetalShaderPipeline(m_ctx, vertFunc, fragFunc, static_cast(vtxFmt), targetSamples, srcFac, dstFac, depthTest, depthWrite, backfaceCulling); if (!m_deferredData.get()) diff --git a/lib/graphicsdev/Vulkan.cpp b/lib/graphicsdev/Vulkan.cpp new file mode 100644 index 0000000..a660ebc --- /dev/null +++ b/lib/graphicsdev/Vulkan.cpp @@ -0,0 +1,160 @@ +#include "boo/graphicsdev/Vulkan.hpp" +#include "boo/IGraphicsContext.hpp" +#include +#include +#include + +#include + +#undef min +#undef max + +static const TBuiltInResource DefaultBuiltInResource = +{ + 32, + 6, + 32, + 32, + 64, + 4096, + 64, + 32, + 80, + 32, + 4096, + 32, + 128, + 8, + 16, + 16, + 15, + -8, + 7, + 8, + 65535, + 65535, + 65535, + 1024, + 1024, + 64, + 1024, + 16, + 8, + 8, + 1, + 60, + 64, + 64, + 128, + 128, + 8, + 8, + 8, + 0, + 0, + 0, + 0, + 0, + 8, + 8, + 16, + 256, + 1024, + 1024, + 64, + 128, + 128, + 16, + 1024, + 4096, + 128, + 128, + 16, + 1024, + 120, + 32, + 64, + 16, + 0, + 0, + 0, + 0, + 8, + 8, + 1, + 0, + 0, + 0, + 0, + 1, + 1, + 16384, + 4, + 64, + 8, + 8, + 4, + + { + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1 + } +}; + +namespace boo +{ +static LogVisor::LogModule Log("boo::Vulkan"); + +IShaderPipeline* VulkanDataFactory::newShaderPipeline +(const char* vertSource, const char* fragSource, + std::vector& vertBlobOut, std::vector& fragBlobOut, + std::vector& pipelineBlob, + size_t texCount, const char* texArrayName, + size_t uniformBlockCount, const char** uniformBlockNames, + BlendFactor srcFac, BlendFactor dstFac, + bool depthTest, bool depthWrite, bool backfaceCulling) +{ + if (vertBlobOut.empty() || fragBlobOut.empty()) + { + glslang::TShader vs(EShLangVertex); + vs.setStrings(&vertSource, 1); + if (!vs.parse(&DefaultBuiltInResource, 110, true, EShMsgDefault)) + { + Log.report(LogVisor::Error, "unable to compile vertex shader\n%s", vs.getInfoLog()); + return nullptr; + } + + glslang::TShader fs(EShLangFragment); + fs.setStrings(&fragSource, 1); + if (!fs.parse(&DefaultBuiltInResource, 110, true, EShMsgDefault)) + { + Log.report(LogVisor::Error, "unable to compile fragment shader\n%s", fs.getInfoLog()); + return nullptr; + } + + glslang::TProgram prog; + prog.addShader(&vs); + prog.addShader(&fs); + if (!prog.link(EShMsgDefault)) + { + Log.report(LogVisor::Error, "unable to link shader program\n%s", prog.getInfoLog()); + return nullptr; + } + + glslang::GlslangToSpv(*prog.getIntermediate(EShLangVertex), vertBlobOut); + glslang::GlslangToSpv(*prog.getIntermediate(EShLangFragment), fragBlobOut); + } + + /* TODO: The actual Vulkan API stuff */ + + return nullptr; +} + +} diff --git a/lib/mac/ApplicationCocoa.mm b/lib/mac/ApplicationCocoa.mm index 4dafbed..f369c96 100644 --- a/lib/mac/ApplicationCocoa.mm +++ b/lib/mac/ApplicationCocoa.mm @@ -16,7 +16,6 @@ namespace boo {class ApplicationCocoa;} { boo::ApplicationCocoa* m_app; @public - NSPanel* aboutPanel; } - (id)initWithApp:(boo::ApplicationCocoa*)app; @end @@ -69,36 +68,20 @@ public: [[NSApplication sharedApplication] setDelegate:m_appDelegate]; /* App menu */ - NSMenu* appMenu = [[NSMenu alloc] initWithTitle:@"main"]; - NSMenu* rwkMenu = [[NSMenu alloc] initWithTitle:[NSString stringWithUTF8String:m_friendlyName.c_str()]]; - [rwkMenu addItemWithTitle:[NSString stringWithFormat:@"About %s", m_friendlyName.c_str()] - action:@selector(aboutApp:) - keyEquivalent:@""]; - NSMenuItem* fsItem = [rwkMenu addItemWithTitle:@"Toggle Full Screen" + NSMenu* rootMenu = [[NSMenu alloc] initWithTitle:@"main"]; + NSMenu* appMenu = [[NSMenu alloc] initWithTitle:[NSString stringWithUTF8String:m_friendlyName.c_str()]]; + NSMenuItem* fsItem = [appMenu addItemWithTitle:@"Toggle Full Screen" action:@selector(toggleFs:) keyEquivalent:@"f"]; [fsItem setKeyEquivalentModifierMask:NSCommandKeyMask]; - [rwkMenu addItem:[NSMenuItem separatorItem]]; - NSMenuItem* quit_item = [rwkMenu addItemWithTitle:[NSString stringWithFormat:@"Quit %s", m_friendlyName.c_str()] - action:@selector(quitApp:) - keyEquivalent:@"q"]; - [quit_item setKeyEquivalentModifierMask:NSCommandKeyMask]; - [[appMenu addItemWithTitle:[NSString stringWithUTF8String:m_friendlyName.c_str()] - action:nil keyEquivalent:@""] setSubmenu:rwkMenu]; - [[NSApplication sharedApplication] setMainMenu:appMenu]; - - /* About panel */ - NSRect aboutCr = NSMakeRect(0, 0, 300, 220); - aboutPanel = [[NSPanel alloc] initWithContentRect:aboutCr - styleMask:NSUtilityWindowMask|NSTitledWindowMask|NSClosableWindowMask - backing:NSBackingStoreBuffered defer:YES]; - [aboutPanel setTitle:[NSString stringWithFormat:@"About %s", m_friendlyName.c_str()]]; - NSText* aboutText = [[NSText alloc] initWithFrame:aboutCr]; - [aboutText setEditable:NO]; - [aboutText setAlignment:NSCenterTextAlignment]; - [aboutText setString:@"\nBoo Authors\n\nJackoalan\nAntidote\n"]; - [aboutPanel setContentView:aboutText]; - m_appDelegate->aboutPanel = aboutPanel; + [appMenu addItem:[NSMenuItem separatorItem]]; + NSMenuItem* quitItem = [appMenu addItemWithTitle:[NSString stringWithFormat:@"Quit %s", m_friendlyName.c_str()] + action:@selector(quitApp:) + keyEquivalent:@"q"]; + [quitItem setKeyEquivalentModifierMask:NSCommandKeyMask]; + [[rootMenu addItemWithTitle:[NSString stringWithUTF8String:m_friendlyName.c_str()] + action:nil keyEquivalent:@""] setSubmenu:appMenu]; + [[NSApplication sharedApplication] setMainMenu:rootMenu]; /* Determine which graphics API to use */ #if BOO_HAS_METAL @@ -106,7 +89,7 @@ public: if (!arg.compare("--metal")) { m_metalCtx.m_dev = MTLCreateSystemDefaultDevice(); - m_metalCtx.m_q = [m_metalCtx.m_dev.get() newCommandQueue]; + m_metalCtx.m_q = [m_metalCtx.m_dev newCommandQueue]; Log.report(LogVisor::Info, "using Metal renderer"); break; } @@ -133,8 +116,10 @@ public: m_clientReturn = m_callback.appMain(this); /* Cleanup here */ + std::vector> toDelete; + toDelete.reserve(m_windows.size()); for (auto& window : m_windows) - delete window.second; + toDelete.emplace_back(window.second); }); /* Already in Cocoa's event loop; return now */ @@ -245,16 +230,6 @@ int ApplicationRun(IApplication::EPlatformType platform, (void)sender; return YES; } -- (IBAction)aboutApp:(id)sender -{ - (void)sender; - NSRect screenFrame = [[aboutPanel screen] frame]; - CGFloat xPos = NSWidth(screenFrame)/2 - 300/2; - CGFloat yPos = NSHeight(screenFrame)/2 - 220/2; - NSRect aboutCr = NSMakeRect(xPos, yPos, 300, 220); - [aboutPanel setFrame:aboutCr display:NO]; - [aboutPanel makeKeyAndOrderFront:self]; -} - (IBAction)toggleFs:(id)sender { (void)sender; diff --git a/lib/mac/CocoaCommon.hpp b/lib/mac/CocoaCommon.hpp index f457a54..d748ee0 100644 --- a/lib/mac/CocoaCommon.hpp +++ b/lib/mac/CocoaCommon.hpp @@ -7,40 +7,6 @@ #endif #include -#include - -template -class NSPtr -{ - void* m_ptr = nullptr; -public: - NSPtr() = default; - ~NSPtr() - { - T ptr = (__bridge_transfer T)m_ptr; - (void)ptr; - } - NSPtr(T&& recv) {*this = std::move(recv);} - NSPtr& operator=(T&& recv) - { - T old = (__bridge_transfer T)m_ptr; - (void)old; - m_ptr = (__bridge_retained void*)recv; - return *this; - } - NSPtr(const NSPtr& other) = delete; - NSPtr(NSPtr&& other) = default; - NSPtr& operator=(const NSPtr& other) = delete; - NSPtr& operator=(NSPtr&& other) = default; - operator bool() const {return m_ptr != 0;} - T get() const {return (__bridge T)m_ptr;} - void reset() - { - T old = (__bridge_transfer T)m_ptr; - (void)old; - m_ptr = nullptr; - } -}; #if __MAC_OS_X_VERSION_MAX_ALLOWED >= 101100 #define BOO_HAS_METAL 1 @@ -55,8 +21,8 @@ namespace boo class IWindow; struct MetalContext { - NSPtr> m_dev; - NSPtr> m_q; + id m_dev = nullptr; + id m_q = nullptr; struct Window { CAMetalLayer* m_metalLayer = nullptr; diff --git a/lib/mac/WindowCocoa.mm b/lib/mac/WindowCocoa.mm index 2102e00..f0e56d7 100644 --- a/lib/mac/WindowCocoa.mm +++ b/lib/mac/WindowCocoa.mm @@ -1107,8 +1107,8 @@ static boo::ESpecialKey translateKeycode(short code) - (void)reshape { - boo::SWindowRect rect = {{int(self.frame.origin.x), int(self.frame.origin.y)}, - {int(self.frame.size.width), int(self.frame.size.height)}}; + boo::SWindowRect rect = {int(self.frame.origin.x), int(self.frame.origin.y), + int(self.frame.size.width), int(self.frame.size.height)}; if (resp->booContext->m_callback) resp->booContext->m_callback->resized(rect); [super reshape]; @@ -1154,7 +1154,7 @@ static boo::ESpecialKey translateKeycode(short code) - (CALayer*)makeBackingLayer { CAMetalLayer* layer = [CAMetalLayer new]; - layer.device = m_ctx->m_dev.get(); + layer.device = m_ctx->m_dev; layer.pixelFormat = MTLPixelFormatBGRA8Unorm; layer.framebufferOnly = NO; return layer; @@ -1177,8 +1177,8 @@ static boo::ESpecialKey translateKeycode(short code) - (void)reshapeHandler { - boo::SWindowRect rect = {{int(self.frame.origin.x), int(self.frame.origin.y)}, - {int(self.frame.size.width), int(self.frame.size.height)}}; + boo::SWindowRect rect = {int(self.frame.origin.x), int(self.frame.origin.y), + int(self.frame.size.width), int(self.frame.size.height)}; boo::MetalContext::Window& w = m_ctx->m_windows[m_window]; std::unique_lock lk(w.m_resizeLock); if (resp->booContext->m_callback) @@ -1222,34 +1222,31 @@ class WindowCocoa : public IWindow WindowCocoaInternal* m_nsWindow; GraphicsContextCocoa* m_gfxCtx; EMouseCursor m_cursor = EMouseCursor::None; + bool m_closed = false; public: WindowCocoa(const std::string& title, NSOpenGLContext* lastGLCtx, MetalContext* metalCtx) { - dispatch_sync(dispatch_get_main_queue(), - ^{ - m_nsWindow = [[WindowCocoaInternal alloc] initWithBooWindow:this title:title]; + m_nsWindow = [[WindowCocoaInternal alloc] initWithBooWindow:this title:title]; #if BOO_HAS_METAL - if (metalCtx->m_dev) - m_gfxCtx = static_cast(_GraphicsContextCocoaMetalNew(IGraphicsContext::EGraphicsAPI::Metal, this, metalCtx)); - else + if (metalCtx->m_dev) + m_gfxCtx = static_cast(_GraphicsContextCocoaMetalNew(IGraphicsContext::EGraphicsAPI::Metal, this, metalCtx)); + else #endif - m_gfxCtx = static_cast(_GraphicsContextCocoaGLNew(IGraphicsContext::EGraphicsAPI::OpenGL3_3, this, lastGLCtx)); - m_gfxCtx->initializeContext(); - }); + m_gfxCtx = static_cast(_GraphicsContextCocoaGLNew(IGraphicsContext::EGraphicsAPI::OpenGL3_3, this, lastGLCtx)); + m_gfxCtx->initializeContext(); } void _clearWindow() { - /* Caller consumes reference on its own */ - (void)(__bridge_retained void*)m_nsWindow; - m_nsWindow = nullptr; + m_closed = true; } ~WindowCocoa() { - [m_nsWindow orderOut:nil]; + if (!m_closed) + [m_nsWindow orderOut:nil]; delete m_gfxCtx; APP->_deletedWindow(this); } @@ -1309,6 +1306,9 @@ public: case EMouseCursor::IBeam: [[NSCursor IBeamCursor] set]; break; + case EMouseCursor::Crosshairs: + [[NSCursor crosshairCursor] set]; + break; default: break; } }); @@ -1491,7 +1491,12 @@ public: IWindow* _WindowCocoaNew(const SystemString& title, NSOpenGLContext* lastGLCtx, MetalContext* metalCtx) { - return new WindowCocoa(title, lastGLCtx, metalCtx); + __block IWindow* window = nullptr; + dispatch_sync(dispatch_get_main_queue(), + ^{ + window = new WindowCocoa(title, lastGLCtx, metalCtx); + }); + return window; } } @@ -1506,6 +1511,7 @@ IWindow* _WindowCocoaNew(const SystemString& title, NSOpenGLContext* lastGLCtx, NSResizableWindowMask backing:NSBackingStoreBuffered defer:YES]; + self.releasedWhenClosed = NO; self.title = [NSString stringWithUTF8String:title.c_str()]; booWindow = bw; return self; diff --git a/lib/win/ApplicationWin32.cpp b/lib/win/ApplicationWin32.cpp index 63646a5..951f979 100644 --- a/lib/win/ApplicationWin32.cpp +++ b/lib/win/ApplicationWin32.cpp @@ -97,6 +97,7 @@ public: WIN32_CURSORS.m_hResize = LoadCursor(nullptr, IDC_SIZEWE); WIN32_CURSORS.m_vResize = LoadCursor(nullptr, IDC_SIZENS); WIN32_CURSORS.m_ibeam = LoadCursor(nullptr, IDC_IBEAM); + WIN32_CURSORS.m_crosshairs = LoadCursor(nullptr, IDC_CROSS); WIN32_CURSORS.m_wait = LoadCursor(nullptr, IDC_WAIT); HMODULE dxgilib = LoadLibraryW(L"dxgi.dll"); diff --git a/lib/win/Win32Common.hpp b/lib/win/Win32Common.hpp index ee31028..30d1e83 100644 --- a/lib/win/Win32Common.hpp +++ b/lib/win/Win32Common.hpp @@ -261,6 +261,7 @@ struct Win32Cursors HCURSOR m_hResize; HCURSOR m_vResize; HCURSOR m_ibeam; + HCURSOR m_crosshairs; HCURSOR m_wait; }; namespace boo diff --git a/lib/win/WindowWin32.cpp b/lib/win/WindowWin32.cpp index c468fb7..e02ac1e 100644 --- a/lib/win/WindowWin32.cpp +++ b/lib/win/WindowWin32.cpp @@ -698,6 +698,8 @@ class WindowWin32 : public IWindow return WIN32_CURSORS.m_vResize; case EMouseCursor::IBeam: return WIN32_CURSORS.m_ibeam; + case EMouseCursor::Crosshairs: + return WIN32_CURSORS.m_crosshairs; default: break; } return WIN32_CURSORS.m_arrow; diff --git a/lib/x11/ApplicationXlib.hpp b/lib/x11/ApplicationXlib.hpp index d97c348..668ff01 100644 --- a/lib/x11/ApplicationXlib.hpp +++ b/lib/x11/ApplicationXlib.hpp @@ -163,7 +163,7 @@ class ApplicationXlib final : public IApplication std::unordered_map m_windows; Display* m_xDisp = nullptr; - XIM m_xIM; + XIM m_xIM = nullptr; XFontSet m_fontset; XIMStyle m_bestStyle = 0; int m_xDefaultScreen = 0; @@ -260,51 +260,49 @@ public: if (XSetLocaleModifiers("") == nullptr) Log.report(LogVisor::Warning, "Cannot set locale modifiers."); - if ((m_xIM = XOpenIM(m_xDisp, nullptr, nullptr, nullptr)) == nullptr) + if ((m_xIM = XOpenIM(m_xDisp, nullptr, nullptr, nullptr))) { - Log.report(LogVisor::FatalError, "Couldn't open input method."); - return; - } + char** missing_charsets; + int num_missing_charsets = 0; + char* default_string; + m_fontset = XCreateFontSet(m_xDisp, + "-adobe-helvetica-*-r-*-*-*-120-*-*-*-*-*-*,\ + -misc-fixed-*-r-*-*-*-130-*-*-*-*-*-*", + &missing_charsets, &num_missing_charsets, + &default_string); - char** missing_charsets; - int num_missing_charsets = 0; - char* default_string; - m_fontset = XCreateFontSet(m_xDisp, - "-adobe-helvetica-*-r-*-*-*-120-*-*-*-*-*-*,\ - -misc-fixed-*-r-*-*-*-130-*-*-*-*-*-*", - &missing_charsets, &num_missing_charsets, - &default_string); - - /* figure out which styles the IM can support */ - XIMStyles* im_supported_styles; - XIMStyle app_supported_styles; - XGetIMValues(m_xIM, XNQueryInputStyle, &im_supported_styles, nullptr); - /* set flags for the styles our application can support */ - app_supported_styles = XIMPreeditNone | XIMPreeditNothing | XIMPreeditPosition; - app_supported_styles |= XIMStatusNone | XIMStatusNothing; - /* - * now look at each of the IM supported styles, and - * chose the "best" one that we can support. - */ - for (int i=0 ; icount_styles ; ++i) - { - XIMStyle style = im_supported_styles->supported_styles[i]; - if ((style & app_supported_styles) == style) /* if we can handle it */ - m_bestStyle = ChooseBetterStyle(style, m_bestStyle); + /* figure out which styles the IM can support */ + XIMStyles* im_supported_styles; + XIMStyle app_supported_styles; + XGetIMValues(m_xIM, XNQueryInputStyle, &im_supported_styles, nullptr); + /* set flags for the styles our application can support */ + app_supported_styles = XIMPreeditNone | XIMPreeditNothing | XIMPreeditPosition; + app_supported_styles |= XIMStatusNone | XIMStatusNothing; + /* + * now look at each of the IM supported styles, and + * chose the "best" one that we can support. + */ + for (int i=0 ; icount_styles ; ++i) + { + XIMStyle style = im_supported_styles->supported_styles[i]; + if ((style & app_supported_styles) == style) /* if we can handle it */ + m_bestStyle = ChooseBetterStyle(style, m_bestStyle); + } + /* if we couldn't support any of them, print an error and exit */ + if (m_bestStyle == 0) + { + Log.report(LogVisor::FatalError, "interaction style not supported."); + return; + } + XFree(im_supported_styles); } - /* if we couldn't support any of them, print an error and exit */ - if (m_bestStyle == 0) - { - Log.report(LogVisor::FatalError, "interaction style not supported."); - return; - } - XFree(im_supported_styles); m_xDefaultScreen = DefaultScreen(m_xDisp); X_CURSORS.m_pointer = XCreateFontCursor(m_xDisp, XC_left_ptr); X_CURSORS.m_hArrow = XCreateFontCursor(m_xDisp, XC_sb_h_double_arrow); X_CURSORS.m_vArrow = XCreateFontCursor(m_xDisp, XC_sb_v_double_arrow); X_CURSORS.m_ibeam = XCreateFontCursor(m_xDisp, XC_xterm); + X_CURSORS.m_crosshairs = XCreateFontCursor(m_xDisp, XC_cross); X_CURSORS.m_wait = XCreateFontCursor(m_xDisp, XC_watch); /* The xkb extension requests that the X server does not diff --git a/lib/x11/WindowXlib.cpp b/lib/x11/WindowXlib.cpp index d013b2e..d1332e0 100644 --- a/lib/x11/WindowXlib.cpp +++ b/lib/x11/WindowXlib.cpp @@ -495,11 +495,7 @@ public: } void present() - { - XLockDisplay(m_xDisp); - glXSwapBuffers(m_xDisp, m_glxWindow); - XUnlockDisplay(m_xDisp); - } + { glXSwapBuffers(m_xDisp, m_glxWindow); } }; @@ -510,7 +506,7 @@ class WindowXlib : public IWindow Colormap m_colormapId; Window m_windowId; XIMStyle m_bestStyle; - XIC m_xIC; + XIC m_xIC = nullptr; GraphicsContextGLX m_gfxCtx; uint32_t m_visualId; @@ -525,7 +521,7 @@ class WindowXlib : public IWindow double m_vScrollLast = 0.0; /* Cached window rectangle (to avoid repeated X queries) */ - int m_wx, m_wy, m_ww, m_wh; + boo::SWindowRect m_wrect; float m_pixelFactor; bool m_inFs = false; @@ -547,6 +543,8 @@ class WindowXlib : public IWindow return X_CURSORS.m_vArrow; case EMouseCursor::IBeam: return X_CURSORS.m_ibeam; + case EMouseCursor::Crosshairs: + return X_CURSORS.m_crosshairs; default: break; } return X_CURSORS.m_pointer; @@ -603,26 +601,24 @@ public: * Now go create an IC using the style we chose. * Also set the window and fontset attributes now. */ - XPoint pt = {0,0}; - XVaNestedList nlist; - m_xIC = XCreateIC(xIM, XNInputStyle, bestInputStyle, - XNClientWindow, m_windowId, - XNFocusWindow, m_windowId, - XNPreeditAttributes, nlist = XVaCreateNestedList(0, - XNSpotLocation, &pt, - XNFontSet, fontset, - nullptr), - nullptr); - XFree(nlist); - if (m_xIC == nullptr) + if (xIM) { - Log.report(LogVisor::FatalError, "Couldn't create input context."); - return; + XPoint pt = {0,0}; + XVaNestedList nlist; + m_xIC = XCreateIC(xIM, XNInputStyle, bestInputStyle, + XNClientWindow, m_windowId, + XNFocusWindow, m_windowId, + XNPreeditAttributes, nlist = XVaCreateNestedList(0, + XNSpotLocation, &pt, + XNFontSet, fontset, + nullptr), + nullptr); + XFree(nlist); + long im_event_mask; + XGetICValues(m_xIC, XNFilterEvents, &im_event_mask, nullptr); + XSelectInput(display, m_windowId, swa.event_mask | im_event_mask); + XSetICFocus(m_xIC); } - long im_event_mask; - XGetICValues(m_xIC, XNFilterEvents, &im_event_mask, nullptr); - XSelectInput(display, m_windowId, swa.event_mask | im_event_mask); - XSetICFocus(m_xIC); /* The XInput 2.1 extension enables per-pixel smooth scrolling trackpads */ XIEventMask mask = {XIAllMasterDevices, XIMaskLen(XI_LASTEVENT)}; @@ -905,20 +901,23 @@ public: void claimKeyboardFocus(const int coord[2]) { - XLockDisplay(m_xDisp); - if (!coord) + if (m_xIC) { - XUnsetICFocus(m_xIC); + XLockDisplay(m_xDisp); + if (!coord) + { + XUnsetICFocus(m_xIC); + XUnlockDisplay(m_xDisp); + return; + } + getWindowFrame(m_wrect.location[0], m_wrect.location[1], m_wrect.size[0], m_wrect.size[1]); + XPoint pt = {short(coord[0]), short(m_wrect.size[1] - coord[1])}; + XVaNestedList list = XVaCreateNestedList(0, XNSpotLocation, &pt, nullptr); + XSetICValues(m_xIC, XNPreeditAttributes, list, nullptr); + XFree(list); + XSetICFocus(m_xIC); XUnlockDisplay(m_xDisp); - return; } - getWindowFrame(m_wx, m_wy, m_ww, m_wh); - XPoint pt = {short(coord[0]), short(m_wh - coord[1])}; - XVaNestedList list = XVaCreateNestedList(0, XNSpotLocation, &pt, nullptr); - XSetICValues(m_xIC, XNPreeditAttributes, list, nullptr); - XFree(list); - XSetICFocus(m_xIC); - XUnlockDisplay(m_xDisp); } bool clipboardCopy(EClipboardType type, const uint8_t* data, size_t sz) @@ -1108,39 +1107,40 @@ public: SWindowCoord MakeButtonEventCoord(XEvent* event) const { int x = event->xbutton.x; - int y = m_wh-event->xbutton.y; + int y = m_wrect.size[1]-event->xbutton.y; return { {x, y}, {int(x / m_pixelFactor), int(y / m_pixelFactor)}, - {x / float(m_ww), y / float(m_wh)} + {x / float(m_wrect.size[0]), y / float(m_wrect.size[1])} }; } SWindowCoord MakeMotionEventCoord(XEvent* event) const { int x = event->xmotion.x; - int y = m_wh-event->xmotion.y; + int y = m_wrect.size[1]-event->xmotion.y; return { {x, y}, {int(x / m_pixelFactor), int(y / m_pixelFactor)}, - {x / float(m_ww), y / float(m_wh)} + {x / float(m_wrect.size[0]), y / float(m_wrect.size[1])} }; } SWindowCoord MakeCrossingEventCoord(XEvent* event) const { int x = event->xcrossing.x; - int y = m_wh-event->xcrossing.y; + int y = m_wrect.size[1]-event->xcrossing.y; return { {x, y}, {int(x / m_pixelFactor), int(y / m_pixelFactor)}, - {x / float(m_ww), y / float(m_wh)} + {x / float(m_wrect.size[0]), y / float(m_wrect.size[1])} }; } +#if 0 /* This procedure sets the application's size constraints and returns * the IM's preferred size for either the Preedit or Status areas, * depending on the value of the name argument. The area argument is @@ -1167,6 +1167,7 @@ public: XSetICValues(m_xIC, name, list, nullptr); XFree(list); } +#endif void _incomingEvent(void* e) { @@ -1194,16 +1195,14 @@ public: int x, y; XTranslateCoordinates(m_xDisp, m_windowId, DefaultRootWindow(m_xDisp), event->xexpose.x, event->xexpose.y, &x, &y, &nw); XGetWindowAttributes(m_xDisp, m_windowId, &wxa); - m_wx = x - wxa.x; - m_wy = y - wxa.y; - m_ww = event->xexpose.width; - m_wh = event->xexpose.height; + m_wrect.location[0] = x - wxa.x; + m_wrect.location[1] = y - wxa.y; + m_wrect.size[0] = event->xexpose.width; + m_wrect.size[1] = event->xexpose.height; if (m_callback) { - SWindowRect rect = - { {m_wx, m_wy}, {m_ww, m_wh} }; XUnlockDisplay(m_xDisp); - m_callback->resized(rect); + m_callback->resized(m_wrect); XLockDisplay(m_xDisp); } return; @@ -1215,17 +1214,13 @@ public: int x, y; XTranslateCoordinates(m_xDisp, m_windowId, DefaultRootWindow(m_xDisp), event->xconfigure.x, event->xconfigure.y, &x, &y, &nw); XGetWindowAttributes(m_xDisp, m_windowId, &wxa); - m_wx = x - wxa.x; - m_wy = y - wxa.y; - m_ww = event->xconfigure.width; - m_wh = event->xconfigure.height; + m_wrect.location[0] = x - wxa.x; + m_wrect.location[1] = y - wxa.y; + m_wrect.size[0] = event->xconfigure.width; + m_wrect.size[1] = event->xconfigure.height; if (m_callback) - { - SWindowRect rect = - { {m_wx, m_wy}, {m_ww, m_wh} }; - m_callback->windowMoved(rect); - } + m_callback->windowMoved(m_wrect); return; } case KeyPress: @@ -1236,13 +1231,16 @@ public: EModifierKey modifierKey; unsigned int state = event->xkey.state; event->xkey.state &= ~ControlMask; - std::string utf8Frag = translateUTF8(&event->xkey, m_xIC); ITextInputCallback* inputCb = m_callback->getTextInputCallback(); - if (utf8Frag.size()) + if (m_xIC) { - if (inputCb) - inputCb->insertText(utf8Frag); - return; + std::string utf8Frag = translateUTF8(&event->xkey, m_xIC); + if (utf8Frag.size()) + { + if (inputCb) + inputCb->insertText(utf8Frag); + return; + } } char charCode = translateKeysym(&event->xkey, specialKey, modifierKey); EModifierKey modifierMask = translateModifiers(state); @@ -1283,7 +1281,7 @@ public: { if (m_callback) { - getWindowFrame(m_wx, m_wy, m_ww, m_wh); + getWindowFrame(m_wrect.location[0], m_wrect.location[1], m_wrect.size[0], m_wrect.size[1]); EMouseButton button = translateButton(event->xbutton.button); if (button != EMouseButton::None) { @@ -1318,7 +1316,7 @@ public: { if (m_callback) { - getWindowFrame(m_wx, m_wy, m_ww, m_wh); + getWindowFrame(m_wrect.location[0], m_wrect.location[1], m_wrect.size[0], m_wrect.size[1]); EMouseButton button = translateButton(event->xbutton.button); if (button != EMouseButton::None) { @@ -1345,7 +1343,7 @@ public: { if (m_callback) { - getWindowFrame(m_wx, m_wy, m_ww, m_wh); + getWindowFrame(m_wrect.location[0], m_wrect.location[1], m_wrect.size[0], m_wrect.size[1]); m_callback->mouseMove(MakeMotionEventCoord(event)); } return; @@ -1354,7 +1352,7 @@ public: { if (m_callback) { - getWindowFrame(m_wx, m_wy, m_ww, m_wh); + getWindowFrame(m_wrect.location[0], m_wrect.location[1], m_wrect.size[0], m_wrect.size[1]); m_callback->mouseEnter(MakeCrossingEventCoord(event)); } return; @@ -1363,7 +1361,7 @@ public: { if (m_callback) { - getWindowFrame(m_wx, m_wy, m_ww, m_wh); + getWindowFrame(m_wrect.location[0], m_wrect.location[1], m_wrect.size[0], m_wrect.size[1]); m_callback->mouseLeave(MakeCrossingEventCoord(event)); } return; @@ -1372,7 +1370,7 @@ public: { if (event->xgeneric.extension == XINPUT_OPCODE) { - getWindowFrame(m_wx, m_wy, m_ww, m_wh); + getWindowFrame(m_wrect.location[0], m_wrect.location[1], m_wrect.size[0], m_wrect.size[1]); switch (event->xgeneric.evtype) { case XI_Motion: @@ -1416,12 +1414,12 @@ public: if (m_callback && didScroll) { int event_x = int(ev->event_x) >> 16; - int event_y = m_wh - (int(ev->event_y) >> 16); + int event_y = m_wrect.size[1] - (int(ev->event_y) >> 16); SWindowCoord coord = { {event_x, event_y}, {int(event_x / m_pixelFactor), int(event_y / m_pixelFactor)}, - {event_x / float(m_ww), event_y / float(m_wh)} + {event_x / float(m_wrect.size[0]), event_y / float(m_wrect.size[1])} }; m_callback->scroll(coord, scrollDelta); } diff --git a/lib/x11/XlibCommon.hpp b/lib/x11/XlibCommon.hpp index c0c79a1..d046694 100644 --- a/lib/x11/XlibCommon.hpp +++ b/lib/x11/XlibCommon.hpp @@ -12,6 +12,7 @@ struct XlibCursors Cursor m_hArrow; Cursor m_vArrow; Cursor m_ibeam; + Cursor m_crosshairs; Cursor m_wait; }; extern XlibCursors X_CURSORS;