mirror of https://github.com/AxioDL/boo.git
Merge branch 'master' of https://github.com/AxioDL/libBoo
This commit is contained in:
commit
6c5e8f5fe8
|
@ -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
|
||||
|
|
|
@ -16,10 +16,12 @@ 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)
|
||||
|
@ -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
|
||||
|
|
8
LICENSE
8
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
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 0ea3c3f01acf58fefdfc7be3333022b8e84e1997
|
|
@ -4,6 +4,7 @@
|
|||
#include "System.hpp"
|
||||
#include <memory>
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
|
||||
#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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;}
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,82 @@
|
|||
#ifndef GDEV_VULKAN_HPP
|
||||
#define GDEV_VULKAN_HPP
|
||||
|
||||
#include "IGraphicsDataFactory.hpp"
|
||||
#include "IGraphicsCommandQueue.hpp"
|
||||
#include "boo/IGraphicsContext.hpp"
|
||||
#include <vector>
|
||||
#include <unordered_set>
|
||||
#include <mutex>
|
||||
|
||||
namespace boo
|
||||
{
|
||||
|
||||
class VulkanDataFactory : public IGraphicsDataFactory
|
||||
{
|
||||
friend struct VulkanCommandQueue;
|
||||
IGraphicsContext* m_parent;
|
||||
static ThreadLocalPtr<struct GLData> m_deferredData;
|
||||
std::unordered_set<struct GLData*> m_committedData;
|
||||
std::mutex m_committedMutex;
|
||||
std::vector<int> 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<uint8_t[]>&& 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<uint8_t[]>&& 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<unsigned int>& vertBlobOut, std::vector<unsigned int>& fragBlobOut,
|
||||
std::vector<unsigned int>& 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<unsigned int> vertBlob;
|
||||
std::vector<unsigned int> fragBlob;
|
||||
std::vector<unsigned int> 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
|
|
@ -98,7 +98,7 @@
|
|||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/Xmd.h>
|
||||
#include <GL/glew.h>
|
||||
#include "glew.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
|
|
@ -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<uint8_t[]> 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<uint8_t[]> 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,18 +234,29 @@ 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;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
ITextureS*
|
||||
|
@ -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<GLCommandQueue*>(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<GLCommandQueue*>(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);
|
||||
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);}
|
||||
|
|
|
@ -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<id<MTLBuffer>> m_buf;
|
||||
id<MTLBuffer> 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<id<MTLBuffer>> m_bufs[2];
|
||||
id<MTLBuffer> m_bufs[2];
|
||||
MetalGraphicsBufferD() = default;
|
||||
|
||||
void load(const void* data, size_t sz);
|
||||
|
@ -95,20 +95,19 @@ class MetalTextureS : public ITextureS
|
|||
default: break;
|
||||
}
|
||||
|
||||
NSPtr<MTLTextureDescriptor*> desc;
|
||||
@autoreleasepool
|
||||
{
|
||||
desc = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:pfmt
|
||||
MTLTextureDescriptor* 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()];
|
||||
desc.usage = MTLTextureUsageShaderRead;
|
||||
desc.mipmapLevelCount = mips;
|
||||
m_tex = [ctx->m_dev newTextureWithDescriptor:desc];
|
||||
const uint8_t* dataIt = reinterpret_cast<const uint8_t*>(data);
|
||||
for (size_t i=0 ; i<mips ; ++i)
|
||||
{
|
||||
[m_tex.get() replaceRegion:MTLRegionMake2D(0, 0, width, height)
|
||||
[m_tex replaceRegion:MTLRegionMake2D(0, 0, width, height)
|
||||
mipmapLevel:i
|
||||
withBytes:dataIt
|
||||
bytesPerRow:width * ppitch];
|
||||
|
@ -117,8 +116,9 @@ class MetalTextureS : public ITextureS
|
|||
height /= 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
public:
|
||||
NSPtr<id<MTLTexture>> m_tex;
|
||||
id<MTLTexture> m_tex;
|
||||
~MetalTextureS() = default;
|
||||
};
|
||||
|
||||
|
@ -139,21 +139,20 @@ class MetalTextureSA : public ITextureSA
|
|||
default: break;
|
||||
}
|
||||
|
||||
NSPtr<MTLTextureDescriptor*> desc;
|
||||
@autoreleasepool
|
||||
{
|
||||
desc = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:pfmt
|
||||
MTLTextureDescriptor* 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()];
|
||||
desc.textureType = MTLTextureType2DArray;
|
||||
desc.arrayLength = layers;
|
||||
desc.usage = MTLTextureUsageShaderRead;
|
||||
m_tex = [ctx->m_dev newTextureWithDescriptor:desc];
|
||||
const uint8_t* dataIt = reinterpret_cast<const uint8_t*>(data);
|
||||
for (size_t i=0 ; i<layers ; ++i)
|
||||
{
|
||||
[m_tex.get() replaceRegion:MTLRegionMake2D(0, 0, width, height)
|
||||
[m_tex replaceRegion:MTLRegionMake2D(0, 0, width, height)
|
||||
mipmapLevel:0
|
||||
slice:i
|
||||
withBytes:dataIt
|
||||
|
@ -162,8 +161,9 @@ class MetalTextureSA : public ITextureSA
|
|||
dataIt += width * height * ppitch;
|
||||
}
|
||||
}
|
||||
}
|
||||
public:
|
||||
NSPtr<id<MTLTexture>> m_tex;
|
||||
id<MTLTexture> 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<MTLTextureDescriptor*> desc;
|
||||
@autoreleasepool
|
||||
{
|
||||
desc = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:format
|
||||
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<id<MTLTexture>> m_texs[2];
|
||||
id<MTLTexture> 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<MTLTextureDescriptor*> desc;
|
||||
@autoreleasepool
|
||||
{
|
||||
desc = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatBGRA8Unorm
|
||||
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()];
|
||||
m_tex = [ctx->m_dev newTextureWithDescriptor:desc];
|
||||
|
||||
if (samples > 1)
|
||||
{
|
||||
desc.get().textureType = MTLTextureType2DMultisample;
|
||||
desc.get().sampleCount = samples;
|
||||
m_msaaTex = [ctx->m_dev.get() newTextureWithDescriptor:desc.get()];
|
||||
desc.textureType = MTLTextureType2DMultisample;
|
||||
desc.sampleCount = samples;
|
||||
m_msaaTex = [ctx->m_dev newTextureWithDescriptor:desc];
|
||||
|
||||
desc.get().pixelFormat = MTLPixelFormatDepth32Float;
|
||||
m_depthTex = [ctx->m_dev.get() newTextureWithDescriptor:desc.get()];
|
||||
desc.pixelFormat = MTLPixelFormatDepth32Float;
|
||||
m_depthTex = [ctx->m_dev newTextureWithDescriptor:desc];
|
||||
|
||||
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.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.get().depthAttachment.texture = m_depthTex.get();
|
||||
m_passDesc.get().depthAttachment.loadAction = MTLLoadActionClear;
|
||||
m_passDesc.get().depthAttachment.storeAction = MTLStoreActionDontCare;
|
||||
m_passDesc.depthAttachment.texture = m_depthTex;
|
||||
m_passDesc.depthAttachment.loadAction = MTLLoadActionClear;
|
||||
m_passDesc.depthAttachment.storeAction = MTLStoreActionDontCare;
|
||||
}
|
||||
else
|
||||
{
|
||||
desc.get().pixelFormat = MTLPixelFormatDepth32Float;
|
||||
m_depthTex = [ctx->m_dev.get() newTextureWithDescriptor:desc.get()];
|
||||
desc.pixelFormat = MTLPixelFormatDepth32Float;
|
||||
m_depthTex = [ctx->m_dev newTextureWithDescriptor:desc];
|
||||
|
||||
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.colorAttachments[0].texture = m_tex;
|
||||
m_passDesc.colorAttachments[0].loadAction = MTLLoadActionClear;
|
||||
m_passDesc.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_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<id<MTLTexture>> m_tex;
|
||||
NSPtr<id<MTLTexture>> m_msaaTex;
|
||||
NSPtr<id<MTLTexture>> m_depthTex;
|
||||
NSPtr<MTLRenderPassDescriptor*> m_passDesc;
|
||||
id<MTLTexture> m_tex;
|
||||
id<MTLTexture> m_msaaTex;
|
||||
id<MTLTexture> 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<MTLTexture> getRenderColorRes() {if (m_samples > 1) return m_msaaTex.get(); return m_tex.get();}
|
||||
id<MTLTexture> 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<MTLVertexDescriptor*> 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 ; i<elementCount ; ++i)
|
||||
{
|
||||
const VertexElementDescriptor* elemin = &elements[i];
|
||||
MTLVertexAttributeDescriptor* attrDesc = m_vdesc.get().attributes[i];
|
||||
MTLVertexAttributeDescriptor* attrDesc = m_vdesc.attributes[i];
|
||||
int semantic = int(elemin->semantic & VertexSemantic::SemanticMask);
|
||||
if ((elemin->semantic & VertexSemantic::Instanced) != VertexSemantic::None)
|
||||
{
|
||||
|
@ -415,40 +415,40 @@ class MetalShaderPipeline : public IShaderPipeline
|
|||
if (backfaceCulling)
|
||||
m_cullMode = MTLCullModeBack;
|
||||
|
||||
NSPtr<MTLRenderPipelineDescriptor*> 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<MTLDepthStencilDescriptor*> 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<id<MTLRenderPipelineState>> m_state;
|
||||
NSPtr<id<MTLDepthStencilState>> m_dsState;
|
||||
id<MTLRenderPipelineState> m_state;
|
||||
id<MTLDepthStencilState> m_dsState;
|
||||
~MetalShaderPipeline() = default;
|
||||
MetalShaderPipeline& operator=(const MetalShaderPipeline&) = delete;
|
||||
MetalShaderPipeline(const MetalShaderPipeline&) = delete;
|
||||
|
||||
void bind(id<MTLRenderCommandEncoder> 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<MTLBuffer> GetBufferGPUResource(const IGraphicsBuffer* buf, int idx)
|
|||
if (buf->dynamic())
|
||||
{
|
||||
const MetalGraphicsBufferD* cbuf = static_cast<const MetalGraphicsBufferD*>(buf);
|
||||
return cbuf->m_bufs[idx].get();
|
||||
return cbuf->m_bufs[idx];
|
||||
}
|
||||
else
|
||||
{
|
||||
const MetalGraphicsBufferS* cbuf = static_cast<const MetalGraphicsBufferS*>(buf);
|
||||
return cbuf->m_buf.get();
|
||||
return cbuf->m_buf;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -474,22 +474,22 @@ static id<MTLTexture> GetTextureGPUResource(const ITexture* tex, int idx)
|
|||
case TextureType::Dynamic:
|
||||
{
|
||||
const MetalTextureD* ctex = static_cast<const MetalTextureD*>(tex);
|
||||
return ctex->m_texs[idx].get();
|
||||
return ctex->m_texs[idx];
|
||||
}
|
||||
case TextureType::Static:
|
||||
{
|
||||
const MetalTextureS* ctex = static_cast<const MetalTextureS*>(tex);
|
||||
return ctex->m_tex.get();
|
||||
return ctex->m_tex;
|
||||
}
|
||||
case TextureType::StaticArray:
|
||||
{
|
||||
const MetalTextureSA* ctex = static_cast<const MetalTextureSA*>(tex);
|
||||
return ctex->m_tex.get();
|
||||
return ctex->m_tex;
|
||||
}
|
||||
case TextureType::Render:
|
||||
{
|
||||
const MetalTextureR* ctex = static_cast<const MetalTextureR*>(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<id<MTLCommandBuffer>> m_cmdBuf;
|
||||
NSPtr<id<MTLRenderCommandEncoder>> m_enc;
|
||||
id<MTLCommandBuffer> m_cmdBuf;
|
||||
id<MTLRenderCommandEncoder> 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<MetalShaderDataBinding*>(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<MetalTextureR*>(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,12 +654,12 @@ 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
|
||||
[m_enc drawIndexedPrimitives:m_primType
|
||||
indexCount:count
|
||||
indexType:MTLIndexTypeUInt32
|
||||
indexBuffer:GetBufferGPUResource(m_boundData->m_ibuf, m_fillBuf)
|
||||
|
@ -668,12 +668,12 @@ struct MetalCommandQueue : IGraphicsCommandQueue
|
|||
|
||||
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
|
||||
[m_enc drawIndexedPrimitives:m_primType
|
||||
indexCount:count
|
||||
indexType:MTLIndexTypeUInt32
|
||||
indexBuffer:GetBufferGPUResource(m_boundData->m_ibuf, m_fillBuf)
|
||||
|
@ -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<MTLTexture> 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<MTLBlitCommandEncoder> blitEnc = [m_cmdBuf.get() blitCommandEncoder];
|
||||
[blitEnc copyFromTexture:m_needsDisplay->m_tex.get()
|
||||
id<MTLBlitCommandEncoder> 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<MTLCommandBuffer> buf) {m_inProgress = false;}];
|
||||
[m_cmdBuf addCompletedHandler:^(id<MTLCommandBuffer> 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<MTLBuffer> res = m_bufs[b].get();
|
||||
id<MTLBuffer> 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<MTLTexture> res = m_texs[b].get();
|
||||
id<MTLTexture> 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<MTLCompileOptions*> compOpts = [MTLCompileOptions new];
|
||||
compOpts.get().languageVersion = MTLLanguageVersion1_1;
|
||||
MTLCompileOptions* compOpts = [MTLCompileOptions new];
|
||||
compOpts.languageVersion = MTLLanguageVersion1_1;
|
||||
NSError* err = nullptr;
|
||||
|
||||
NSPtr<id<MTLLibrary>> vertShaderLib = [m_ctx->m_dev.get() newLibraryWithSource:@(vertSource)
|
||||
options:compOpts.get()
|
||||
id<MTLLibrary> 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<id<MTLFunction>> vertFunc = [vertShaderLib.get() newFunctionWithName:@"vmain"];
|
||||
id<MTLFunction> vertFunc = [vertShaderLib newFunctionWithName:@"vmain"];
|
||||
|
||||
NSPtr<id<MTLLibrary>> fragShaderLib = [m_ctx->m_dev.get() newLibraryWithSource:@(fragSource)
|
||||
options:compOpts.get()
|
||||
id<MTLLibrary> 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<id<MTLFunction>> fragFunc = [fragShaderLib.get() newFunctionWithName:@"fmain"];
|
||||
id<MTLFunction> fragFunc = [fragShaderLib newFunctionWithName:@"fmain"];
|
||||
|
||||
MetalShaderPipeline* retval = new MetalShaderPipeline(m_ctx, vertFunc.get(), fragFunc.get(),
|
||||
MetalShaderPipeline* retval = new MetalShaderPipeline(m_ctx, vertFunc, fragFunc,
|
||||
static_cast<const MetalVertexFormat*>(vtxFmt), targetSamples,
|
||||
srcFac, dstFac, depthTest, depthWrite, backfaceCulling);
|
||||
if (!m_deferredData.get())
|
||||
|
|
|
@ -0,0 +1,160 @@
|
|||
#include "boo/graphicsdev/Vulkan.hpp"
|
||||
#include "boo/IGraphicsContext.hpp"
|
||||
#include <vector>
|
||||
#include <glslang/Public/ShaderLang.h>
|
||||
#include <SPIRV/GlslangToSpv.h>
|
||||
|
||||
#include <LogVisor/LogVisor.hpp>
|
||||
|
||||
#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<unsigned int>& vertBlobOut, std::vector<unsigned int>& fragBlobOut,
|
||||
std::vector<unsigned int>& 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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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()]
|
||||
[appMenu addItem:[NSMenuItem separatorItem]];
|
||||
NSMenuItem* quitItem = [appMenu 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;
|
||||
[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<std::unique_ptr<IWindow>> 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;
|
||||
|
|
|
@ -7,40 +7,6 @@
|
|||
#endif
|
||||
|
||||
#include <Availability.h>
|
||||
#include <utility>
|
||||
|
||||
template <class T>
|
||||
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<id<MTLDevice>> m_dev;
|
||||
NSPtr<id<MTLCommandQueue>> m_q;
|
||||
id<MTLDevice> m_dev = nullptr;
|
||||
id<MTLCommandQueue> m_q = nullptr;
|
||||
struct Window
|
||||
{
|
||||
CAMetalLayer* m_metalLayer = nullptr;
|
||||
|
|
|
@ -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<std::mutex> lk(w.m_resizeLock);
|
||||
if (resp->booContext->m_callback)
|
||||
|
@ -1222,13 +1222,12 @@ 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];
|
||||
#if BOO_HAS_METAL
|
||||
if (metalCtx->m_dev)
|
||||
|
@ -1237,18 +1236,16 @@ public:
|
|||
#endif
|
||||
m_gfxCtx = static_cast<GraphicsContextCocoa*>(_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()
|
||||
{
|
||||
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;
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -261,6 +261,7 @@ struct Win32Cursors
|
|||
HCURSOR m_hResize;
|
||||
HCURSOR m_vResize;
|
||||
HCURSOR m_ibeam;
|
||||
HCURSOR m_crosshairs;
|
||||
HCURSOR m_wait;
|
||||
};
|
||||
namespace boo
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -163,7 +163,7 @@ class ApplicationXlib final : public IApplication
|
|||
std::unordered_map<Window, IWindow*> 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,12 +260,8 @@ 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;
|
||||
|
@ -299,12 +295,14 @@ public:
|
|||
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
|
||||
|
|
|
@ -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,6 +601,8 @@ public:
|
|||
* Now go create an IC using the style we chose.
|
||||
* Also set the window and fontset attributes now.
|
||||
*/
|
||||
if (xIM)
|
||||
{
|
||||
XPoint pt = {0,0};
|
||||
XVaNestedList nlist;
|
||||
m_xIC = XCreateIC(xIM, XNInputStyle, bestInputStyle,
|
||||
|
@ -614,15 +614,11 @@ public:
|
|||
nullptr),
|
||||
nullptr);
|
||||
XFree(nlist);
|
||||
if (m_xIC == nullptr)
|
||||
{
|
||||
Log.report(LogVisor::FatalError, "Couldn't create input context.");
|
||||
return;
|
||||
}
|
||||
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)};
|
||||
|
@ -904,6 +900,8 @@ public:
|
|||
} m_clipData;
|
||||
|
||||
void claimKeyboardFocus(const int coord[2])
|
||||
{
|
||||
if (m_xIC)
|
||||
{
|
||||
XLockDisplay(m_xDisp);
|
||||
if (!coord)
|
||||
|
@ -912,14 +910,15 @@ public:
|
|||
XUnlockDisplay(m_xDisp);
|
||||
return;
|
||||
}
|
||||
getWindowFrame(m_wx, m_wy, m_ww, m_wh);
|
||||
XPoint pt = {short(coord[0]), short(m_wh - coord[1])};
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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,14 +1231,17 @@ 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 (m_xIC)
|
||||
{
|
||||
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);
|
||||
if (charCode)
|
||||
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue