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"]
|
[submodule "LogVisor"]
|
||||||
path = LogVisor
|
path = LogVisor
|
||||||
url = https://github.com/AxioDL/LogVisor.git
|
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)
|
if(NOT GEKKO AND NOT CAFE)
|
||||||
list(APPEND PLAT_SRCS
|
list(APPEND PLAT_SRCS
|
||||||
lib/graphicsdev/GL.cpp
|
lib/graphicsdev/GL.cpp
|
||||||
|
lib/graphicsdev/Vulkan.cpp
|
||||||
lib/graphicsdev/glew.c)
|
lib/graphicsdev/glew.c)
|
||||||
|
|
||||||
list(APPEND PLAT_HDRS
|
list(APPEND PLAT_HDRS
|
||||||
include/boo/graphicsdev/GL.hpp)
|
include/boo/graphicsdev/GL.hpp
|
||||||
|
include/boo/graphicsdev/Vulkan.hpp)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(WIN32)
|
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)
|
set_source_files_properties(lib/graphicsdev/glew.c PROPERTIES COMPILE_FLAGS -Os)
|
||||||
endif()
|
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_LIBS ${_BOO_SYS_LIBS} CACHE PATH "Boo System Libraries" FORCE)
|
||||||
set(BOO_SYS_DEFINES ${_BOO_SYS_DEFINES} CACHE PATH "Boo System Defines" FORCE)
|
set(BOO_SYS_DEFINES ${_BOO_SYS_DEFINES} CACHE PATH "Boo System Defines" FORCE)
|
||||||
|
|
||||||
add_definitions(${_BOO_SYS_DEFINES})
|
add_definitions(${_BOO_SYS_DEFINES})
|
||||||
include_directories(include)
|
include_directories(include glslang)
|
||||||
|
|
||||||
add_library(Boo
|
add_library(Boo
|
||||||
lib/inputdev/CafeProPad.cpp include/boo/inputdev/CafeProPad.hpp
|
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
|
Copyright (c) 2015 libBoo Contributors
|
||||||
Original Authors: Jack Andersen and Phillip "Antidote" Stephens
|
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
|
The above copyright notice and this permission notice shall be included in all
|
||||||
copies or substantial portions of the Software.
|
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
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
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 "System.hpp"
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
#undef min
|
#undef min
|
||||||
#undef max
|
#undef max
|
||||||
|
@ -35,7 +36,7 @@ struct SWindowRect
|
||||||
int location[2];
|
int location[2];
|
||||||
int size[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)
|
SWindowRect(int x, int y, int w, int h)
|
||||||
{
|
{
|
||||||
|
@ -240,7 +241,8 @@ enum class EMouseCursor
|
||||||
Pointer = 1,
|
Pointer = 1,
|
||||||
HorizontalArrow = 2,
|
HorizontalArrow = 2,
|
||||||
VerticalArrow = 3,
|
VerticalArrow = 3,
|
||||||
IBeam = 4
|
IBeam = 4,
|
||||||
|
Crosshairs = 5
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class EClipboardType
|
enum class EClipboardType
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#ifndef GDEV_GLES3_HPP
|
#ifndef GDEV_GL_HPP
|
||||||
#define GDEV_GLES3_HPP
|
#define GDEV_GL_HPP
|
||||||
|
|
||||||
#include "IGraphicsDataFactory.hpp"
|
#include "IGraphicsDataFactory.hpp"
|
||||||
#include "IGraphicsCommandQueue.hpp"
|
#include "IGraphicsCommandQueue.hpp"
|
||||||
|
@ -63,4 +63,4 @@ public:
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // GDEV_GLES3_HPP
|
#endif // GDEV_GL_HPP
|
||||||
|
|
|
@ -184,6 +184,7 @@ struct IGraphicsDataFactory
|
||||||
D3D11,
|
D3D11,
|
||||||
D3D12,
|
D3D12,
|
||||||
Metal,
|
Metal,
|
||||||
|
Vulkan,
|
||||||
GX,
|
GX,
|
||||||
GX2
|
GX2
|
||||||
};
|
};
|
||||||
|
@ -292,6 +293,7 @@ public:
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
~GraphicsDataToken() {doDestroy();}
|
~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/Xlib.h>
|
||||||
#include <X11/Xutil.h>
|
#include <X11/Xutil.h>
|
||||||
#include <X11/Xmd.h>
|
#include <X11/Xmd.h>
|
||||||
#include <GL/glew.h>
|
#include "glew.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
|
@ -66,16 +66,20 @@ class GLGraphicsBufferD : public IGraphicsBufferD
|
||||||
{
|
{
|
||||||
friend class GLDataFactory;
|
friend class GLDataFactory;
|
||||||
friend struct GLCommandQueue;
|
friend struct GLCommandQueue;
|
||||||
struct GLCommandQueue* m_q;
|
|
||||||
GLuint m_bufs[3];
|
GLuint m_bufs[3];
|
||||||
GLenum m_target;
|
GLenum m_target;
|
||||||
std::unique_ptr<uint8_t[]> m_cpuBuf;
|
std::unique_ptr<uint8_t[]> m_cpuBuf;
|
||||||
size_t m_cpuSz = 0;
|
size_t m_cpuSz = 0;
|
||||||
int m_validMask = 0;
|
int m_validMask = 0;
|
||||||
GLGraphicsBufferD(GLCommandQueue* q, BufferUse use, size_t sz)
|
GLGraphicsBufferD(BufferUse use, size_t sz)
|
||||||
: m_q(q), m_target(USE_TABLE[int(use)]), m_cpuBuf(new uint8_t[sz]), m_cpuSz(sz)
|
: m_target(USE_TABLE[int(use)]), m_cpuBuf(new uint8_t[sz]), m_cpuSz(sz)
|
||||||
{
|
{
|
||||||
glGenBuffers(3, m_bufs);
|
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);
|
void update(int b);
|
||||||
public:
|
public:
|
||||||
|
@ -193,7 +197,6 @@ class GLTextureD : public ITextureD
|
||||||
{
|
{
|
||||||
friend class GLDataFactory;
|
friend class GLDataFactory;
|
||||||
friend struct GLCommandQueue;
|
friend struct GLCommandQueue;
|
||||||
struct GLCommandQueue* m_q;
|
|
||||||
GLuint m_texs[3];
|
GLuint m_texs[3];
|
||||||
std::unique_ptr<uint8_t[]> m_cpuBuf;
|
std::unique_ptr<uint8_t[]> m_cpuBuf;
|
||||||
size_t m_cpuSz = 0;
|
size_t m_cpuSz = 0;
|
||||||
|
@ -201,7 +204,7 @@ class GLTextureD : public ITextureD
|
||||||
size_t m_width = 0;
|
size_t m_width = 0;
|
||||||
size_t m_height = 0;
|
size_t m_height = 0;
|
||||||
int m_validMask = 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);
|
void update(int b);
|
||||||
public:
|
public:
|
||||||
~GLTextureD();
|
~GLTextureD();
|
||||||
|
@ -223,6 +226,7 @@ class GLTextureR : public ITextureR
|
||||||
size_t m_width = 0;
|
size_t m_width = 0;
|
||||||
size_t m_height = 0;
|
size_t m_height = 0;
|
||||||
size_t m_samples = 0;
|
size_t m_samples = 0;
|
||||||
|
GLenum m_target;
|
||||||
GLTextureR(GLCommandQueue* q, size_t width, size_t height, size_t samples);
|
GLTextureR(GLCommandQueue* q, size_t width, size_t height, size_t samples);
|
||||||
public:
|
public:
|
||||||
~GLTextureR();
|
~GLTextureR();
|
||||||
|
@ -230,18 +234,29 @@ public:
|
||||||
void bind(size_t idx) const
|
void bind(size_t idx) const
|
||||||
{
|
{
|
||||||
glActiveTexture(GL_TEXTURE0 + idx);
|
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)
|
void resize(size_t width, size_t height)
|
||||||
{
|
{
|
||||||
m_width = width;
|
m_width = width;
|
||||||
m_height = height;
|
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]);
|
glBindTexture(GL_TEXTURE_2D, m_texs[0]);
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
|
||||||
glBindTexture(GL_TEXTURE_2D, m_texs[1]);
|
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);
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, width, height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, nullptr);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
ITextureS*
|
ITextureS*
|
||||||
|
@ -1142,7 +1157,7 @@ void GLGraphicsBufferD::update(int b)
|
||||||
if ((slot & m_validMask) == 0)
|
if ((slot & m_validMask) == 0)
|
||||||
{
|
{
|
||||||
glBindBuffer(m_target, m_bufs[b]);
|
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;
|
m_validMask |= slot;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1173,18 +1188,17 @@ void GLGraphicsBufferD::bindUniform(size_t idx, int b)
|
||||||
IGraphicsBufferD*
|
IGraphicsBufferD*
|
||||||
GLDataFactory::newDynamicBuffer(BufferUse use, size_t stride, size_t count)
|
GLDataFactory::newDynamicBuffer(BufferUse use, size_t stride, size_t count)
|
||||||
{
|
{
|
||||||
GLCommandQueue* q = static_cast<GLCommandQueue*>(m_parent->getCommandQueue());
|
GLGraphicsBufferD* retval = new GLGraphicsBufferD(use, stride * count);
|
||||||
GLGraphicsBufferD* retval = new GLGraphicsBufferD(q, use, stride * count);
|
|
||||||
if (!m_deferredData.get())
|
if (!m_deferredData.get())
|
||||||
m_deferredData.reset(new struct GLData());
|
m_deferredData.reset(new struct GLData());
|
||||||
m_deferredData->m_DBufs.emplace_back(retval);
|
m_deferredData->m_DBufs.emplace_back(retval);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLTextureD::GLTextureD(GLCommandQueue* q, size_t width, size_t height, TextureFormat fmt)
|
GLTextureD::GLTextureD(size_t width, size_t height, TextureFormat fmt)
|
||||||
: m_q(q), m_width(width), m_height(height)
|
: m_width(width), m_height(height)
|
||||||
{
|
{
|
||||||
int pxPitch;
|
int pxPitch = 4;
|
||||||
switch (fmt)
|
switch (fmt)
|
||||||
{
|
{
|
||||||
case TextureFormat::RGBA8:
|
case TextureFormat::RGBA8:
|
||||||
|
@ -1250,8 +1264,7 @@ void GLTextureD::bind(size_t idx, int b)
|
||||||
ITextureD*
|
ITextureD*
|
||||||
GLDataFactory::newDynamicTexture(size_t width, size_t height, TextureFormat fmt)
|
GLDataFactory::newDynamicTexture(size_t width, size_t height, TextureFormat fmt)
|
||||||
{
|
{
|
||||||
GLCommandQueue* q = static_cast<GLCommandQueue*>(m_parent->getCommandQueue());
|
GLTextureD* retval = new GLTextureD(width, height, fmt);
|
||||||
GLTextureD* retval = new GLTextureD(q, width, height, fmt);
|
|
||||||
if (!m_deferredData.get())
|
if (!m_deferredData.get())
|
||||||
m_deferredData.reset(new struct GLData());
|
m_deferredData.reset(new struct GLData());
|
||||||
m_deferredData->m_DTexs.emplace_back(retval);
|
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)
|
: m_q(q), m_width(width), m_height(height), m_samples(samples)
|
||||||
{
|
{
|
||||||
glGenTextures(2, m_texs);
|
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]);
|
glBindTexture(GL_TEXTURE_2D, m_texs[0]);
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
|
||||||
glBindTexture(GL_TEXTURE_2D, m_texs[1]);
|
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);
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, width, height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, nullptr);
|
||||||
|
}
|
||||||
m_q->addFBO(this);
|
m_q->addFBO(this);
|
||||||
}
|
}
|
||||||
GLTextureR::~GLTextureR() {glDeleteTextures(2, m_texs); m_q->delFBO(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)
|
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_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:
|
public:
|
||||||
size_t m_stride;
|
size_t m_stride;
|
||||||
size_t m_count;
|
size_t m_count;
|
||||||
size_t m_sz;
|
size_t m_sz;
|
||||||
NSPtr<id<MTLBuffer>> m_buf;
|
id<MTLBuffer> m_buf;
|
||||||
~MetalGraphicsBufferS() = default;
|
~MetalGraphicsBufferS() = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -62,15 +62,15 @@ class MetalGraphicsBufferD : public IGraphicsBufferD
|
||||||
: m_q(q), m_stride(stride), m_count(count), m_sz(stride * count)
|
: m_q(q), m_stride(stride), m_count(count), m_sz(stride * count)
|
||||||
{
|
{
|
||||||
m_cpuBuf.reset(new uint8_t[m_sz]);
|
m_cpuBuf.reset(new uint8_t[m_sz]);
|
||||||
m_bufs[0] = [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.get() newBufferWithLength:m_sz options:MTL_DYNAMIC];
|
m_bufs[1] = [ctx->m_dev newBufferWithLength:m_sz options:MTL_DYNAMIC];
|
||||||
}
|
}
|
||||||
void update(int b);
|
void update(int b);
|
||||||
public:
|
public:
|
||||||
size_t m_stride;
|
size_t m_stride;
|
||||||
size_t m_count;
|
size_t m_count;
|
||||||
size_t m_sz;
|
size_t m_sz;
|
||||||
NSPtr<id<MTLBuffer>> m_bufs[2];
|
id<MTLBuffer> m_bufs[2];
|
||||||
MetalGraphicsBufferD() = default;
|
MetalGraphicsBufferD() = default;
|
||||||
|
|
||||||
void load(const void* data, size_t sz);
|
void load(const void* data, size_t sz);
|
||||||
|
@ -95,20 +95,19 @@ class MetalTextureS : public ITextureS
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
|
|
||||||
NSPtr<MTLTextureDescriptor*> desc;
|
|
||||||
@autoreleasepool
|
@autoreleasepool
|
||||||
{
|
{
|
||||||
desc = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:pfmt
|
MTLTextureDescriptor* desc =
|
||||||
|
[MTLTextureDescriptor texture2DDescriptorWithPixelFormat:pfmt
|
||||||
width:width height:height
|
width:width height:height
|
||||||
mipmapped:(mips>1)?YES:NO];
|
mipmapped:(mips>1)?YES:NO];
|
||||||
}
|
desc.usage = MTLTextureUsageShaderRead;
|
||||||
desc.get().usage = MTLTextureUsageShaderRead;
|
desc.mipmapLevelCount = mips;
|
||||||
desc.get().mipmapLevelCount = mips;
|
m_tex = [ctx->m_dev newTextureWithDescriptor:desc];
|
||||||
m_tex = [ctx->m_dev.get() newTextureWithDescriptor:desc.get()];
|
|
||||||
const uint8_t* dataIt = reinterpret_cast<const uint8_t*>(data);
|
const uint8_t* dataIt = reinterpret_cast<const uint8_t*>(data);
|
||||||
for (size_t i=0 ; i<mips ; ++i)
|
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
|
mipmapLevel:i
|
||||||
withBytes:dataIt
|
withBytes:dataIt
|
||||||
bytesPerRow:width * ppitch];
|
bytesPerRow:width * ppitch];
|
||||||
|
@ -117,8 +116,9 @@ class MetalTextureS : public ITextureS
|
||||||
height /= 2;
|
height /= 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
public:
|
public:
|
||||||
NSPtr<id<MTLTexture>> m_tex;
|
id<MTLTexture> m_tex;
|
||||||
~MetalTextureS() = default;
|
~MetalTextureS() = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -139,21 +139,20 @@ class MetalTextureSA : public ITextureSA
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
|
|
||||||
NSPtr<MTLTextureDescriptor*> desc;
|
|
||||||
@autoreleasepool
|
@autoreleasepool
|
||||||
{
|
{
|
||||||
desc = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:pfmt
|
MTLTextureDescriptor* desc =
|
||||||
|
[MTLTextureDescriptor texture2DDescriptorWithPixelFormat:pfmt
|
||||||
width:width height:height
|
width:width height:height
|
||||||
mipmapped:NO];
|
mipmapped:NO];
|
||||||
}
|
desc.textureType = MTLTextureType2DArray;
|
||||||
desc.get().textureType = MTLTextureType2DArray;
|
desc.arrayLength = layers;
|
||||||
desc.get().arrayLength = layers;
|
desc.usage = MTLTextureUsageShaderRead;
|
||||||
desc.get().usage = MTLTextureUsageShaderRead;
|
m_tex = [ctx->m_dev newTextureWithDescriptor:desc];
|
||||||
m_tex = [ctx->m_dev.get() newTextureWithDescriptor:desc.get()];
|
|
||||||
const uint8_t* dataIt = reinterpret_cast<const uint8_t*>(data);
|
const uint8_t* dataIt = reinterpret_cast<const uint8_t*>(data);
|
||||||
for (size_t i=0 ; i<layers ; ++i)
|
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
|
mipmapLevel:0
|
||||||
slice:i
|
slice:i
|
||||||
withBytes:dataIt
|
withBytes:dataIt
|
||||||
|
@ -162,8 +161,9 @@ class MetalTextureSA : public ITextureSA
|
||||||
dataIt += width * height * ppitch;
|
dataIt += width * height * ppitch;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
public:
|
public:
|
||||||
NSPtr<id<MTLTexture>> m_tex;
|
id<MTLTexture> m_tex;
|
||||||
~MetalTextureSA() = default;
|
~MetalTextureSA() = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -199,20 +199,20 @@ class MetalTextureD : public ITextureD
|
||||||
m_cpuSz = width * height * m_pxPitch;
|
m_cpuSz = width * height * m_pxPitch;
|
||||||
m_cpuBuf.reset(new uint8_t[m_cpuSz]);
|
m_cpuBuf.reset(new uint8_t[m_cpuSz]);
|
||||||
|
|
||||||
NSPtr<MTLTextureDescriptor*> desc;
|
|
||||||
@autoreleasepool
|
@autoreleasepool
|
||||||
{
|
{
|
||||||
desc = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:format
|
MTLTextureDescriptor* desc =
|
||||||
|
[MTLTextureDescriptor texture2DDescriptorWithPixelFormat:format
|
||||||
width:width height:height
|
width:width height:height
|
||||||
mipmapped:NO];
|
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);
|
void update(int b);
|
||||||
public:
|
public:
|
||||||
NSPtr<id<MTLTexture>> m_texs[2];
|
id<MTLTexture> m_texs[2];
|
||||||
~MetalTextureD() = default;
|
~MetalTextureD() = default;
|
||||||
|
|
||||||
void load(const void* data, size_t sz);
|
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)
|
void Setup(MetalContext* ctx, size_t width, size_t height, size_t samples)
|
||||||
{
|
{
|
||||||
NSPtr<MTLTextureDescriptor*> desc;
|
|
||||||
@autoreleasepool
|
@autoreleasepool
|
||||||
{
|
{
|
||||||
desc = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatBGRA8Unorm
|
MTLTextureDescriptor* desc =
|
||||||
|
[MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatBGRA8Unorm
|
||||||
width:width height:height
|
width:width height:height
|
||||||
mipmapped:NO];
|
mipmapped:NO];
|
||||||
m_passDesc = [MTLRenderPassDescriptor renderPassDescriptor];
|
m_passDesc = [MTLRenderPassDescriptor renderPassDescriptor];
|
||||||
}
|
desc.usage = MTLTextureUsageRenderTarget | MTLTextureUsageShaderRead;
|
||||||
desc.get().usage = MTLTextureUsageRenderTarget | MTLTextureUsageShaderRead;
|
desc.storageMode = MTLStorageModePrivate;
|
||||||
desc.get().storageMode = MTLStorageModePrivate;
|
|
||||||
|
|
||||||
m_tex = [ctx->m_dev.get() newTextureWithDescriptor:desc.get()];
|
m_tex = [ctx->m_dev newTextureWithDescriptor:desc];
|
||||||
|
|
||||||
if (samples > 1)
|
if (samples > 1)
|
||||||
{
|
{
|
||||||
desc.get().textureType = MTLTextureType2DMultisample;
|
desc.textureType = MTLTextureType2DMultisample;
|
||||||
desc.get().sampleCount = samples;
|
desc.sampleCount = samples;
|
||||||
m_msaaTex = [ctx->m_dev.get() newTextureWithDescriptor:desc.get()];
|
m_msaaTex = [ctx->m_dev newTextureWithDescriptor:desc];
|
||||||
|
|
||||||
desc.get().pixelFormat = MTLPixelFormatDepth32Float;
|
desc.pixelFormat = MTLPixelFormatDepth32Float;
|
||||||
m_depthTex = [ctx->m_dev.get() newTextureWithDescriptor:desc.get()];
|
m_depthTex = [ctx->m_dev newTextureWithDescriptor:desc];
|
||||||
|
|
||||||
m_passDesc.get().colorAttachments[0].texture = m_msaaTex.get();
|
m_passDesc.colorAttachments[0].texture = m_msaaTex;
|
||||||
m_passDesc.get().colorAttachments[0].resolveTexture = m_tex.get();
|
m_passDesc.colorAttachments[0].resolveTexture = m_tex;
|
||||||
m_passDesc.get().colorAttachments[0].loadAction = MTLLoadActionClear;
|
m_passDesc.colorAttachments[0].loadAction = MTLLoadActionClear;
|
||||||
m_passDesc.get().colorAttachments[0].storeAction = MTLStoreActionMultisampleResolve;
|
m_passDesc.colorAttachments[0].storeAction = MTLStoreActionMultisampleResolve;
|
||||||
|
|
||||||
m_passDesc.get().depthAttachment.texture = m_depthTex.get();
|
m_passDesc.depthAttachment.texture = m_depthTex;
|
||||||
m_passDesc.get().depthAttachment.loadAction = MTLLoadActionClear;
|
m_passDesc.depthAttachment.loadAction = MTLLoadActionClear;
|
||||||
m_passDesc.get().depthAttachment.storeAction = MTLStoreActionDontCare;
|
m_passDesc.depthAttachment.storeAction = MTLStoreActionDontCare;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
desc.get().pixelFormat = MTLPixelFormatDepth32Float;
|
desc.pixelFormat = MTLPixelFormatDepth32Float;
|
||||||
m_depthTex = [ctx->m_dev.get() newTextureWithDescriptor:desc.get()];
|
m_depthTex = [ctx->m_dev newTextureWithDescriptor:desc];
|
||||||
|
|
||||||
m_passDesc.get().colorAttachments[0].texture = m_tex.get();
|
m_passDesc.colorAttachments[0].texture = m_tex;
|
||||||
m_passDesc.get().colorAttachments[0].loadAction = MTLLoadActionClear;
|
m_passDesc.colorAttachments[0].loadAction = MTLLoadActionClear;
|
||||||
m_passDesc.get().colorAttachments[0].storeAction = MTLStoreActionStore;
|
m_passDesc.colorAttachments[0].storeAction = MTLStoreActionStore;
|
||||||
|
|
||||||
m_passDesc.get().depthAttachment.texture = m_depthTex.get();
|
m_passDesc.depthAttachment.texture = m_depthTex;
|
||||||
m_passDesc.get().depthAttachment.loadAction = MTLLoadActionClear;
|
m_passDesc.depthAttachment.loadAction = MTLLoadActionClear;
|
||||||
m_passDesc.get().depthAttachment.storeAction = MTLStoreActionDontCare;
|
m_passDesc.depthAttachment.storeAction = MTLStoreActionDontCare;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -284,10 +284,10 @@ class MetalTextureR : public ITextureR
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
size_t samples() const {return m_samples;}
|
size_t samples() const {return m_samples;}
|
||||||
NSPtr<id<MTLTexture>> m_tex;
|
id<MTLTexture> m_tex;
|
||||||
NSPtr<id<MTLTexture>> m_msaaTex;
|
id<MTLTexture> m_msaaTex;
|
||||||
NSPtr<id<MTLTexture>> m_depthTex;
|
id<MTLTexture> m_depthTex;
|
||||||
NSPtr<MTLRenderPassDescriptor*> m_passDesc;
|
MTLRenderPassDescriptor* m_passDesc;
|
||||||
~MetalTextureR() = default;
|
~MetalTextureR() = default;
|
||||||
|
|
||||||
void resize(MetalContext* ctx, size_t width, size_t height)
|
void resize(MetalContext* ctx, size_t width, size_t height)
|
||||||
|
@ -301,7 +301,7 @@ public:
|
||||||
Setup(ctx, width, height, m_samples);
|
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[] =
|
static const size_t SEMANTIC_SIZE_TABLE[] =
|
||||||
|
@ -337,7 +337,7 @@ static const MTLVertexFormat SEMANTIC_TYPE_TABLE[] =
|
||||||
struct MetalVertexFormat : IVertexFormat
|
struct MetalVertexFormat : IVertexFormat
|
||||||
{
|
{
|
||||||
size_t m_elementCount;
|
size_t m_elementCount;
|
||||||
NSPtr<MTLVertexDescriptor*> m_vdesc;
|
MTLVertexDescriptor* m_vdesc;
|
||||||
MetalVertexFormat(size_t elementCount, const VertexElementDescriptor* elements)
|
MetalVertexFormat(size_t elementCount, const VertexElementDescriptor* elements)
|
||||||
: m_elementCount(elementCount)
|
: m_elementCount(elementCount)
|
||||||
{
|
{
|
||||||
|
@ -354,12 +354,12 @@ struct MetalVertexFormat : IVertexFormat
|
||||||
}
|
}
|
||||||
|
|
||||||
m_vdesc = [MTLVertexDescriptor vertexDescriptor];
|
m_vdesc = [MTLVertexDescriptor vertexDescriptor];
|
||||||
MTLVertexBufferLayoutDescriptor* layoutDesc = m_vdesc.get().layouts[0];
|
MTLVertexBufferLayoutDescriptor* layoutDesc = m_vdesc.layouts[0];
|
||||||
layoutDesc.stride = stride;
|
layoutDesc.stride = stride;
|
||||||
layoutDesc.stepFunction = MTLVertexStepFunctionPerVertex;
|
layoutDesc.stepFunction = MTLVertexStepFunctionPerVertex;
|
||||||
layoutDesc.stepRate = 1;
|
layoutDesc.stepRate = 1;
|
||||||
|
|
||||||
layoutDesc = m_vdesc.get().layouts[1];
|
layoutDesc = m_vdesc.layouts[1];
|
||||||
layoutDesc.stride = instStride;
|
layoutDesc.stride = instStride;
|
||||||
layoutDesc.stepFunction = MTLVertexStepFunctionPerInstance;
|
layoutDesc.stepFunction = MTLVertexStepFunctionPerInstance;
|
||||||
layoutDesc.stepRate = 1;
|
layoutDesc.stepRate = 1;
|
||||||
|
@ -369,7 +369,7 @@ struct MetalVertexFormat : IVertexFormat
|
||||||
for (size_t i=0 ; i<elementCount ; ++i)
|
for (size_t i=0 ; i<elementCount ; ++i)
|
||||||
{
|
{
|
||||||
const VertexElementDescriptor* elemin = &elements[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);
|
int semantic = int(elemin->semantic & VertexSemantic::SemanticMask);
|
||||||
if ((elemin->semantic & VertexSemantic::Instanced) != VertexSemantic::None)
|
if ((elemin->semantic & VertexSemantic::Instanced) != VertexSemantic::None)
|
||||||
{
|
{
|
||||||
|
@ -415,40 +415,40 @@ class MetalShaderPipeline : public IShaderPipeline
|
||||||
if (backfaceCulling)
|
if (backfaceCulling)
|
||||||
m_cullMode = MTLCullModeBack;
|
m_cullMode = MTLCullModeBack;
|
||||||
|
|
||||||
NSPtr<MTLRenderPipelineDescriptor*> desc = [MTLRenderPipelineDescriptor new];
|
MTLRenderPipelineDescriptor* desc = [MTLRenderPipelineDescriptor new];
|
||||||
desc.get().vertexFunction = vert;
|
desc.vertexFunction = vert;
|
||||||
desc.get().fragmentFunction = frag;
|
desc.fragmentFunction = frag;
|
||||||
desc.get().vertexDescriptor = vtxFmt->m_vdesc.get();
|
desc.vertexDescriptor = vtxFmt->m_vdesc;
|
||||||
desc.get().sampleCount = targetSamples;
|
desc.sampleCount = targetSamples;
|
||||||
desc.get().colorAttachments[0].pixelFormat = MTLPixelFormatBGRA8Unorm;
|
desc.colorAttachments[0].pixelFormat = MTLPixelFormatBGRA8Unorm;
|
||||||
desc.get().colorAttachments[0].blendingEnabled = dstFac != BlendFactor::Zero;
|
desc.colorAttachments[0].blendingEnabled = dstFac != BlendFactor::Zero;
|
||||||
desc.get().colorAttachments[0].sourceRGBBlendFactor = BLEND_FACTOR_TABLE[int(srcFac)];
|
desc.colorAttachments[0].sourceRGBBlendFactor = BLEND_FACTOR_TABLE[int(srcFac)];
|
||||||
desc.get().colorAttachments[0].destinationRGBBlendFactor = BLEND_FACTOR_TABLE[int(dstFac)];
|
desc.colorAttachments[0].destinationRGBBlendFactor = BLEND_FACTOR_TABLE[int(dstFac)];
|
||||||
desc.get().depthAttachmentPixelFormat = MTLPixelFormatDepth32Float;
|
desc.depthAttachmentPixelFormat = MTLPixelFormatDepth32Float;
|
||||||
desc.get().inputPrimitiveTopology = MTLPrimitiveTopologyClassTriangle;
|
desc.inputPrimitiveTopology = MTLPrimitiveTopologyClassTriangle;
|
||||||
NSError* err = nullptr;
|
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)
|
if (err)
|
||||||
Log.report(LogVisor::FatalError, "error making shader pipeline: %s",
|
Log.report(LogVisor::FatalError, "error making shader pipeline: %s",
|
||||||
[[err localizedDescription] UTF8String]);
|
[[err localizedDescription] UTF8String]);
|
||||||
|
|
||||||
NSPtr<MTLDepthStencilDescriptor*> dsDesc = [MTLDepthStencilDescriptor new];
|
MTLDepthStencilDescriptor* dsDesc = [MTLDepthStencilDescriptor new];
|
||||||
if (depthTest)
|
if (depthTest)
|
||||||
dsDesc.get().depthCompareFunction = MTLCompareFunctionLessEqual;
|
dsDesc.depthCompareFunction = MTLCompareFunctionLessEqual;
|
||||||
dsDesc.get().depthWriteEnabled = depthWrite;
|
dsDesc.depthWriteEnabled = depthWrite;
|
||||||
m_dsState = [ctx->m_dev.get() newDepthStencilStateWithDescriptor:dsDesc.get()];
|
m_dsState = [ctx->m_dev newDepthStencilStateWithDescriptor:dsDesc];
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
NSPtr<id<MTLRenderPipelineState>> m_state;
|
id<MTLRenderPipelineState> m_state;
|
||||||
NSPtr<id<MTLDepthStencilState>> m_dsState;
|
id<MTLDepthStencilState> m_dsState;
|
||||||
~MetalShaderPipeline() = default;
|
~MetalShaderPipeline() = default;
|
||||||
MetalShaderPipeline& operator=(const MetalShaderPipeline&) = delete;
|
MetalShaderPipeline& operator=(const MetalShaderPipeline&) = delete;
|
||||||
MetalShaderPipeline(const MetalShaderPipeline&) = delete;
|
MetalShaderPipeline(const MetalShaderPipeline&) = delete;
|
||||||
|
|
||||||
void bind(id<MTLRenderCommandEncoder> enc)
|
void bind(id<MTLRenderCommandEncoder> enc)
|
||||||
{
|
{
|
||||||
[enc setRenderPipelineState:m_state.get()];
|
[enc setRenderPipelineState:m_state];
|
||||||
[enc setDepthStencilState:m_dsState.get()];
|
[enc setDepthStencilState:m_dsState];
|
||||||
[enc setCullMode:m_cullMode];
|
[enc setCullMode:m_cullMode];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -458,12 +458,12 @@ static id<MTLBuffer> GetBufferGPUResource(const IGraphicsBuffer* buf, int idx)
|
||||||
if (buf->dynamic())
|
if (buf->dynamic())
|
||||||
{
|
{
|
||||||
const MetalGraphicsBufferD* cbuf = static_cast<const MetalGraphicsBufferD*>(buf);
|
const MetalGraphicsBufferD* cbuf = static_cast<const MetalGraphicsBufferD*>(buf);
|
||||||
return cbuf->m_bufs[idx].get();
|
return cbuf->m_bufs[idx];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const MetalGraphicsBufferS* cbuf = static_cast<const MetalGraphicsBufferS*>(buf);
|
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:
|
case TextureType::Dynamic:
|
||||||
{
|
{
|
||||||
const MetalTextureD* ctex = static_cast<const MetalTextureD*>(tex);
|
const MetalTextureD* ctex = static_cast<const MetalTextureD*>(tex);
|
||||||
return ctex->m_texs[idx].get();
|
return ctex->m_texs[idx];
|
||||||
}
|
}
|
||||||
case TextureType::Static:
|
case TextureType::Static:
|
||||||
{
|
{
|
||||||
const MetalTextureS* ctex = static_cast<const MetalTextureS*>(tex);
|
const MetalTextureS* ctex = static_cast<const MetalTextureS*>(tex);
|
||||||
return ctex->m_tex.get();
|
return ctex->m_tex;
|
||||||
}
|
}
|
||||||
case TextureType::StaticArray:
|
case TextureType::StaticArray:
|
||||||
{
|
{
|
||||||
const MetalTextureSA* ctex = static_cast<const MetalTextureSA*>(tex);
|
const MetalTextureSA* ctex = static_cast<const MetalTextureSA*>(tex);
|
||||||
return ctex->m_tex.get();
|
return ctex->m_tex;
|
||||||
}
|
}
|
||||||
case TextureType::Render:
|
case TextureType::Render:
|
||||||
{
|
{
|
||||||
const MetalTextureR* ctex = static_cast<const MetalTextureR*>(tex);
|
const MetalTextureR* ctex = static_cast<const MetalTextureR*>(tex);
|
||||||
return ctex->m_tex.get();
|
return ctex->m_tex;
|
||||||
}
|
}
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
|
@ -547,8 +547,8 @@ struct MetalCommandQueue : IGraphicsCommandQueue
|
||||||
MetalContext* m_ctx;
|
MetalContext* m_ctx;
|
||||||
IWindow* m_parentWindow;
|
IWindow* m_parentWindow;
|
||||||
IGraphicsContext* m_parent;
|
IGraphicsContext* m_parent;
|
||||||
NSPtr<id<MTLCommandBuffer>> m_cmdBuf;
|
id<MTLCommandBuffer> m_cmdBuf;
|
||||||
NSPtr<id<MTLRenderCommandEncoder>> m_enc;
|
id<MTLRenderCommandEncoder> m_enc;
|
||||||
bool m_running = true;
|
bool m_running = true;
|
||||||
|
|
||||||
size_t m_fillBuf = 0;
|
size_t m_fillBuf = 0;
|
||||||
|
@ -559,7 +559,7 @@ struct MetalCommandQueue : IGraphicsCommandQueue
|
||||||
{
|
{
|
||||||
@autoreleasepool
|
@autoreleasepool
|
||||||
{
|
{
|
||||||
m_cmdBuf = [ctx->m_q.get() commandBuffer];
|
m_cmdBuf = [ctx->m_q commandBuffer];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -567,7 +567,7 @@ struct MetalCommandQueue : IGraphicsCommandQueue
|
||||||
{
|
{
|
||||||
m_running = false;
|
m_running = false;
|
||||||
if (m_inProgress)
|
if (m_inProgress)
|
||||||
[m_cmdBuf.get() waitUntilCompleted];
|
[m_cmdBuf waitUntilCompleted];
|
||||||
}
|
}
|
||||||
|
|
||||||
~MetalCommandQueue()
|
~MetalCommandQueue()
|
||||||
|
@ -579,7 +579,7 @@ struct MetalCommandQueue : IGraphicsCommandQueue
|
||||||
void setShaderDataBinding(IShaderDataBinding* binding)
|
void setShaderDataBinding(IShaderDataBinding* binding)
|
||||||
{
|
{
|
||||||
MetalShaderDataBinding* cbind = static_cast<MetalShaderDataBinding*>(binding);
|
MetalShaderDataBinding* cbind = static_cast<MetalShaderDataBinding*>(binding);
|
||||||
cbind->bind(m_enc.get(), m_fillBuf);
|
cbind->bind(m_enc, m_fillBuf);
|
||||||
m_boundData = cbind;
|
m_boundData = cbind;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -587,10 +587,10 @@ struct MetalCommandQueue : IGraphicsCommandQueue
|
||||||
void setRenderTarget(ITextureR* target)
|
void setRenderTarget(ITextureR* target)
|
||||||
{
|
{
|
||||||
MetalTextureR* ctarget = static_cast<MetalTextureR*>(target);
|
MetalTextureR* ctarget = static_cast<MetalTextureR*>(target);
|
||||||
[m_enc.get() endEncoding];
|
[m_enc endEncoding];
|
||||||
@autoreleasepool
|
@autoreleasepool
|
||||||
{
|
{
|
||||||
m_enc = [m_cmdBuf.get() renderCommandEncoderWithDescriptor:ctarget->m_passDesc.get()];
|
m_enc = [m_cmdBuf renderCommandEncoderWithDescriptor:ctarget->m_passDesc];
|
||||||
}
|
}
|
||||||
m_boundTarget = ctarget;
|
m_boundTarget = ctarget;
|
||||||
}
|
}
|
||||||
|
@ -599,7 +599,7 @@ struct MetalCommandQueue : IGraphicsCommandQueue
|
||||||
{
|
{
|
||||||
MTLViewport vp = {double(rect.location[0]), double(rect.location[1]),
|
MTLViewport vp = {double(rect.location[0]), double(rect.location[1]),
|
||||||
double(rect.size[0]), double(rect.size[1]), 0.0, 1.0};
|
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)
|
void setScissor(const SWindowRect& rect)
|
||||||
|
@ -609,7 +609,7 @@ struct MetalCommandQueue : IGraphicsCommandQueue
|
||||||
MTLScissorRect scissor = {NSUInteger(rect.location[0]),
|
MTLScissorRect scissor = {NSUInteger(rect.location[0]),
|
||||||
NSUInteger(m_boundTarget->m_height - rect.location[1] - rect.size[1]),
|
NSUInteger(m_boundTarget->m_height - rect.location[1] - rect.size[1]),
|
||||||
NSUInteger(rect.size[0]), NSUInteger(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)
|
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)
|
void drawIndexed(size_t start, size_t count)
|
||||||
{
|
{
|
||||||
[m_enc.get() drawIndexedPrimitives:m_primType
|
[m_enc drawIndexedPrimitives:m_primType
|
||||||
indexCount:count
|
indexCount:count
|
||||||
indexType:MTLIndexTypeUInt32
|
indexType:MTLIndexTypeUInt32
|
||||||
indexBuffer:GetBufferGPUResource(m_boundData->m_ibuf, m_fillBuf)
|
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)
|
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)
|
void drawInstancesIndexed(size_t start, size_t count, size_t instCount)
|
||||||
{
|
{
|
||||||
[m_enc.get() drawIndexedPrimitives:m_primType
|
[m_enc drawIndexedPrimitives:m_primType
|
||||||
indexCount:count
|
indexCount:count
|
||||||
indexType:MTLIndexTypeUInt32
|
indexType:MTLIndexTypeUInt32
|
||||||
indexBuffer:GetBufferGPUResource(m_boundData->m_ibuf, m_fillBuf)
|
indexBuffer:GetBufferGPUResource(m_boundData->m_ibuf, m_fillBuf)
|
||||||
|
@ -707,13 +707,13 @@ struct MetalCommandQueue : IGraphicsCommandQueue
|
||||||
|
|
||||||
@autoreleasepool
|
@autoreleasepool
|
||||||
{
|
{
|
||||||
[m_enc.get() endEncoding];
|
[m_enc endEncoding];
|
||||||
m_enc.reset();
|
m_enc = nullptr;
|
||||||
|
|
||||||
/* Abandon if in progress (renderer too slow) */
|
/* Abandon if in progress (renderer too slow) */
|
||||||
if (m_inProgress)
|
if (m_inProgress)
|
||||||
{
|
{
|
||||||
m_cmdBuf = [m_ctx->m_q.get() commandBuffer];
|
m_cmdBuf = [m_ctx->m_q commandBuffer];
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -723,7 +723,7 @@ struct MetalCommandQueue : IGraphicsCommandQueue
|
||||||
for (const auto& resize : m_texResizes)
|
for (const auto& resize : m_texResizes)
|
||||||
resize.first->resize(m_ctx, resize.second.first, resize.second.second);
|
resize.first->resize(m_ctx, resize.second.first, resize.second.second);
|
||||||
m_texResizes.clear();
|
m_texResizes.clear();
|
||||||
m_cmdBuf = [m_ctx->m_q.get() commandBuffer];
|
m_cmdBuf = [m_ctx->m_q commandBuffer];
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -747,11 +747,11 @@ struct MetalCommandQueue : IGraphicsCommandQueue
|
||||||
if (drawable)
|
if (drawable)
|
||||||
{
|
{
|
||||||
id<MTLTexture> dest = drawable.texture;
|
id<MTLTexture> dest = drawable.texture;
|
||||||
if (m_needsDisplay->m_tex.get().width == dest.width &&
|
if (m_needsDisplay->m_tex.width == dest.width &&
|
||||||
m_needsDisplay->m_tex.get().height == dest.height)
|
m_needsDisplay->m_tex.height == dest.height)
|
||||||
{
|
{
|
||||||
id<MTLBlitCommandEncoder> blitEnc = [m_cmdBuf.get() blitCommandEncoder];
|
id<MTLBlitCommandEncoder> blitEnc = [m_cmdBuf blitCommandEncoder];
|
||||||
[blitEnc copyFromTexture:m_needsDisplay->m_tex.get()
|
[blitEnc copyFromTexture:m_needsDisplay->m_tex
|
||||||
sourceSlice:0
|
sourceSlice:0
|
||||||
sourceLevel:0
|
sourceLevel:0
|
||||||
sourceOrigin:MTLOriginMake(0, 0, 0)
|
sourceOrigin:MTLOriginMake(0, 0, 0)
|
||||||
|
@ -761,7 +761,7 @@ struct MetalCommandQueue : IGraphicsCommandQueue
|
||||||
destinationLevel:0
|
destinationLevel:0
|
||||||
destinationOrigin:MTLOriginMake(0, 0, 0)];
|
destinationOrigin:MTLOriginMake(0, 0, 0)];
|
||||||
[blitEnc endEncoding];
|
[blitEnc endEncoding];
|
||||||
[m_cmdBuf.get() presentDrawable:drawable];
|
[m_cmdBuf presentDrawable:drawable];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -771,10 +771,10 @@ struct MetalCommandQueue : IGraphicsCommandQueue
|
||||||
m_drawBuf = m_fillBuf;
|
m_drawBuf = m_fillBuf;
|
||||||
m_fillBuf ^= 1;
|
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_inProgress = true;
|
||||||
[m_cmdBuf.get() commit];
|
[m_cmdBuf commit];
|
||||||
m_cmdBuf = [m_ctx->m_q.get() commandBuffer];
|
m_cmdBuf = [m_ctx->m_q commandBuffer];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -784,7 +784,7 @@ void MetalGraphicsBufferD::update(int b)
|
||||||
int slot = 1 << b;
|
int slot = 1 << b;
|
||||||
if ((slot & m_validSlots) == 0)
|
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);
|
memcpy(res.contents, m_cpuBuf.get(), m_sz);
|
||||||
m_validSlots |= slot;
|
m_validSlots |= slot;
|
||||||
}
|
}
|
||||||
|
@ -811,7 +811,7 @@ void MetalTextureD::update(int b)
|
||||||
int slot = 1 << b;
|
int slot = 1 << b;
|
||||||
if ((slot & m_validSlots) == 0)
|
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)
|
[res replaceRegion:MTLRegionMake2D(0, 0, m_width, m_height)
|
||||||
mipmapLevel:0 withBytes:m_cpuBuf.get() bytesPerRow:m_width*m_pxPitch];
|
mipmapLevel:0 withBytes:m_cpuBuf.get() bytesPerRow:m_width*m_pxPitch];
|
||||||
m_validSlots |= slot;
|
m_validSlots |= slot;
|
||||||
|
@ -924,25 +924,25 @@ IShaderPipeline* MetalDataFactory::newShaderPipeline(const char* vertSource, con
|
||||||
BlendFactor srcFac, BlendFactor dstFac,
|
BlendFactor srcFac, BlendFactor dstFac,
|
||||||
bool depthTest, bool depthWrite, bool backfaceCulling)
|
bool depthTest, bool depthWrite, bool backfaceCulling)
|
||||||
{
|
{
|
||||||
NSPtr<MTLCompileOptions*> compOpts = [MTLCompileOptions new];
|
MTLCompileOptions* compOpts = [MTLCompileOptions new];
|
||||||
compOpts.get().languageVersion = MTLLanguageVersion1_1;
|
compOpts.languageVersion = MTLLanguageVersion1_1;
|
||||||
NSError* err = nullptr;
|
NSError* err = nullptr;
|
||||||
|
|
||||||
NSPtr<id<MTLLibrary>> vertShaderLib = [m_ctx->m_dev.get() newLibraryWithSource:@(vertSource)
|
id<MTLLibrary> vertShaderLib = [m_ctx->m_dev newLibraryWithSource:@(vertSource)
|
||||||
options:compOpts.get()
|
options:compOpts
|
||||||
error:&err];
|
error:&err];
|
||||||
if (err)
|
if (err)
|
||||||
Log.report(LogVisor::FatalError, "error compiling vert shader: %s", [[err localizedDescription] UTF8String]);
|
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)
|
id<MTLLibrary> fragShaderLib = [m_ctx->m_dev newLibraryWithSource:@(fragSource)
|
||||||
options:compOpts.get()
|
options:compOpts
|
||||||
error:&err];
|
error:&err];
|
||||||
if (err)
|
if (err)
|
||||||
Log.report(LogVisor::FatalError, "error compiling frag shader: %s", [[err localizedDescription] UTF8String]);
|
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,
|
static_cast<const MetalVertexFormat*>(vtxFmt), targetSamples,
|
||||||
srcFac, dstFac, depthTest, depthWrite, backfaceCulling);
|
srcFac, dstFac, depthTest, depthWrite, backfaceCulling);
|
||||||
if (!m_deferredData.get())
|
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;
|
boo::ApplicationCocoa* m_app;
|
||||||
@public
|
@public
|
||||||
NSPanel* aboutPanel;
|
|
||||||
}
|
}
|
||||||
- (id)initWithApp:(boo::ApplicationCocoa*)app;
|
- (id)initWithApp:(boo::ApplicationCocoa*)app;
|
||||||
@end
|
@end
|
||||||
|
@ -69,36 +68,20 @@ public:
|
||||||
[[NSApplication sharedApplication] setDelegate:m_appDelegate];
|
[[NSApplication sharedApplication] setDelegate:m_appDelegate];
|
||||||
|
|
||||||
/* App menu */
|
/* App menu */
|
||||||
NSMenu* appMenu = [[NSMenu alloc] initWithTitle:@"main"];
|
NSMenu* rootMenu = [[NSMenu alloc] initWithTitle:@"main"];
|
||||||
NSMenu* rwkMenu = [[NSMenu alloc] initWithTitle:[NSString stringWithUTF8String:m_friendlyName.c_str()]];
|
NSMenu* appMenu = [[NSMenu alloc] initWithTitle:[NSString stringWithUTF8String:m_friendlyName.c_str()]];
|
||||||
[rwkMenu addItemWithTitle:[NSString stringWithFormat:@"About %s", m_friendlyName.c_str()]
|
NSMenuItem* fsItem = [appMenu addItemWithTitle:@"Toggle Full Screen"
|
||||||
action:@selector(aboutApp:)
|
|
||||||
keyEquivalent:@""];
|
|
||||||
NSMenuItem* fsItem = [rwkMenu addItemWithTitle:@"Toggle Full Screen"
|
|
||||||
action:@selector(toggleFs:)
|
action:@selector(toggleFs:)
|
||||||
keyEquivalent:@"f"];
|
keyEquivalent:@"f"];
|
||||||
[fsItem setKeyEquivalentModifierMask:NSCommandKeyMask];
|
[fsItem setKeyEquivalentModifierMask:NSCommandKeyMask];
|
||||||
[rwkMenu addItem:[NSMenuItem separatorItem]];
|
[appMenu addItem:[NSMenuItem separatorItem]];
|
||||||
NSMenuItem* quit_item = [rwkMenu addItemWithTitle:[NSString stringWithFormat:@"Quit %s", m_friendlyName.c_str()]
|
NSMenuItem* quitItem = [appMenu addItemWithTitle:[NSString stringWithFormat:@"Quit %s", m_friendlyName.c_str()]
|
||||||
action:@selector(quitApp:)
|
action:@selector(quitApp:)
|
||||||
keyEquivalent:@"q"];
|
keyEquivalent:@"q"];
|
||||||
[quit_item setKeyEquivalentModifierMask:NSCommandKeyMask];
|
[quitItem setKeyEquivalentModifierMask:NSCommandKeyMask];
|
||||||
[[appMenu addItemWithTitle:[NSString stringWithUTF8String:m_friendlyName.c_str()]
|
[[rootMenu addItemWithTitle:[NSString stringWithUTF8String:m_friendlyName.c_str()]
|
||||||
action:nil keyEquivalent:@""] setSubmenu:rwkMenu];
|
action:nil keyEquivalent:@""] setSubmenu:appMenu];
|
||||||
[[NSApplication sharedApplication] setMainMenu:appMenu];
|
[[NSApplication sharedApplication] setMainMenu:rootMenu];
|
||||||
|
|
||||||
/* 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;
|
|
||||||
|
|
||||||
/* Determine which graphics API to use */
|
/* Determine which graphics API to use */
|
||||||
#if BOO_HAS_METAL
|
#if BOO_HAS_METAL
|
||||||
|
@ -106,7 +89,7 @@ public:
|
||||||
if (!arg.compare("--metal"))
|
if (!arg.compare("--metal"))
|
||||||
{
|
{
|
||||||
m_metalCtx.m_dev = MTLCreateSystemDefaultDevice();
|
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");
|
Log.report(LogVisor::Info, "using Metal renderer");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -133,8 +116,10 @@ public:
|
||||||
m_clientReturn = m_callback.appMain(this);
|
m_clientReturn = m_callback.appMain(this);
|
||||||
|
|
||||||
/* Cleanup here */
|
/* Cleanup here */
|
||||||
|
std::vector<std::unique_ptr<IWindow>> toDelete;
|
||||||
|
toDelete.reserve(m_windows.size());
|
||||||
for (auto& window : m_windows)
|
for (auto& window : m_windows)
|
||||||
delete window.second;
|
toDelete.emplace_back(window.second);
|
||||||
});
|
});
|
||||||
|
|
||||||
/* Already in Cocoa's event loop; return now */
|
/* Already in Cocoa's event loop; return now */
|
||||||
|
@ -245,16 +230,6 @@ int ApplicationRun(IApplication::EPlatformType platform,
|
||||||
(void)sender;
|
(void)sender;
|
||||||
return YES;
|
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
|
- (IBAction)toggleFs:(id)sender
|
||||||
{
|
{
|
||||||
(void)sender;
|
(void)sender;
|
||||||
|
|
|
@ -7,40 +7,6 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <Availability.h>
|
#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
|
#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 101100
|
||||||
#define BOO_HAS_METAL 1
|
#define BOO_HAS_METAL 1
|
||||||
|
@ -55,8 +21,8 @@ namespace boo
|
||||||
class IWindow;
|
class IWindow;
|
||||||
struct MetalContext
|
struct MetalContext
|
||||||
{
|
{
|
||||||
NSPtr<id<MTLDevice>> m_dev;
|
id<MTLDevice> m_dev = nullptr;
|
||||||
NSPtr<id<MTLCommandQueue>> m_q;
|
id<MTLCommandQueue> m_q = nullptr;
|
||||||
struct Window
|
struct Window
|
||||||
{
|
{
|
||||||
CAMetalLayer* m_metalLayer = nullptr;
|
CAMetalLayer* m_metalLayer = nullptr;
|
||||||
|
|
|
@ -1107,8 +1107,8 @@ static boo::ESpecialKey translateKeycode(short code)
|
||||||
|
|
||||||
- (void)reshape
|
- (void)reshape
|
||||||
{
|
{
|
||||||
boo::SWindowRect rect = {{int(self.frame.origin.x), int(self.frame.origin.y)},
|
boo::SWindowRect rect = {int(self.frame.origin.x), int(self.frame.origin.y),
|
||||||
{int(self.frame.size.width), int(self.frame.size.height)}};
|
int(self.frame.size.width), int(self.frame.size.height)};
|
||||||
if (resp->booContext->m_callback)
|
if (resp->booContext->m_callback)
|
||||||
resp->booContext->m_callback->resized(rect);
|
resp->booContext->m_callback->resized(rect);
|
||||||
[super reshape];
|
[super reshape];
|
||||||
|
@ -1154,7 +1154,7 @@ static boo::ESpecialKey translateKeycode(short code)
|
||||||
- (CALayer*)makeBackingLayer
|
- (CALayer*)makeBackingLayer
|
||||||
{
|
{
|
||||||
CAMetalLayer* layer = [CAMetalLayer new];
|
CAMetalLayer* layer = [CAMetalLayer new];
|
||||||
layer.device = m_ctx->m_dev.get();
|
layer.device = m_ctx->m_dev;
|
||||||
layer.pixelFormat = MTLPixelFormatBGRA8Unorm;
|
layer.pixelFormat = MTLPixelFormatBGRA8Unorm;
|
||||||
layer.framebufferOnly = NO;
|
layer.framebufferOnly = NO;
|
||||||
return layer;
|
return layer;
|
||||||
|
@ -1177,8 +1177,8 @@ static boo::ESpecialKey translateKeycode(short code)
|
||||||
|
|
||||||
- (void)reshapeHandler
|
- (void)reshapeHandler
|
||||||
{
|
{
|
||||||
boo::SWindowRect rect = {{int(self.frame.origin.x), int(self.frame.origin.y)},
|
boo::SWindowRect rect = {int(self.frame.origin.x), int(self.frame.origin.y),
|
||||||
{int(self.frame.size.width), int(self.frame.size.height)}};
|
int(self.frame.size.width), int(self.frame.size.height)};
|
||||||
boo::MetalContext::Window& w = m_ctx->m_windows[m_window];
|
boo::MetalContext::Window& w = m_ctx->m_windows[m_window];
|
||||||
std::unique_lock<std::mutex> lk(w.m_resizeLock);
|
std::unique_lock<std::mutex> lk(w.m_resizeLock);
|
||||||
if (resp->booContext->m_callback)
|
if (resp->booContext->m_callback)
|
||||||
|
@ -1222,13 +1222,12 @@ class WindowCocoa : public IWindow
|
||||||
WindowCocoaInternal* m_nsWindow;
|
WindowCocoaInternal* m_nsWindow;
|
||||||
GraphicsContextCocoa* m_gfxCtx;
|
GraphicsContextCocoa* m_gfxCtx;
|
||||||
EMouseCursor m_cursor = EMouseCursor::None;
|
EMouseCursor m_cursor = EMouseCursor::None;
|
||||||
|
bool m_closed = false;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
WindowCocoa(const std::string& title, NSOpenGLContext* lastGLCtx, MetalContext* metalCtx)
|
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 BOO_HAS_METAL
|
||||||
if (metalCtx->m_dev)
|
if (metalCtx->m_dev)
|
||||||
|
@ -1237,18 +1236,16 @@ public:
|
||||||
#endif
|
#endif
|
||||||
m_gfxCtx = static_cast<GraphicsContextCocoa*>(_GraphicsContextCocoaGLNew(IGraphicsContext::EGraphicsAPI::OpenGL3_3, this, lastGLCtx));
|
m_gfxCtx = static_cast<GraphicsContextCocoa*>(_GraphicsContextCocoaGLNew(IGraphicsContext::EGraphicsAPI::OpenGL3_3, this, lastGLCtx));
|
||||||
m_gfxCtx->initializeContext();
|
m_gfxCtx->initializeContext();
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _clearWindow()
|
void _clearWindow()
|
||||||
{
|
{
|
||||||
/* Caller consumes reference on its own */
|
m_closed = true;
|
||||||
(void)(__bridge_retained void*)m_nsWindow;
|
|
||||||
m_nsWindow = nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
~WindowCocoa()
|
~WindowCocoa()
|
||||||
{
|
{
|
||||||
|
if (!m_closed)
|
||||||
[m_nsWindow orderOut:nil];
|
[m_nsWindow orderOut:nil];
|
||||||
delete m_gfxCtx;
|
delete m_gfxCtx;
|
||||||
APP->_deletedWindow(this);
|
APP->_deletedWindow(this);
|
||||||
|
@ -1309,6 +1306,9 @@ public:
|
||||||
case EMouseCursor::IBeam:
|
case EMouseCursor::IBeam:
|
||||||
[[NSCursor IBeamCursor] set];
|
[[NSCursor IBeamCursor] set];
|
||||||
break;
|
break;
|
||||||
|
case EMouseCursor::Crosshairs:
|
||||||
|
[[NSCursor crosshairCursor] set];
|
||||||
|
break;
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -1491,7 +1491,12 @@ public:
|
||||||
|
|
||||||
IWindow* _WindowCocoaNew(const SystemString& title, NSOpenGLContext* lastGLCtx, MetalContext* metalCtx)
|
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
|
NSResizableWindowMask
|
||||||
backing:NSBackingStoreBuffered
|
backing:NSBackingStoreBuffered
|
||||||
defer:YES];
|
defer:YES];
|
||||||
|
self.releasedWhenClosed = NO;
|
||||||
self.title = [NSString stringWithUTF8String:title.c_str()];
|
self.title = [NSString stringWithUTF8String:title.c_str()];
|
||||||
booWindow = bw;
|
booWindow = bw;
|
||||||
return self;
|
return self;
|
||||||
|
|
|
@ -97,6 +97,7 @@ public:
|
||||||
WIN32_CURSORS.m_hResize = LoadCursor(nullptr, IDC_SIZEWE);
|
WIN32_CURSORS.m_hResize = LoadCursor(nullptr, IDC_SIZEWE);
|
||||||
WIN32_CURSORS.m_vResize = LoadCursor(nullptr, IDC_SIZENS);
|
WIN32_CURSORS.m_vResize = LoadCursor(nullptr, IDC_SIZENS);
|
||||||
WIN32_CURSORS.m_ibeam = LoadCursor(nullptr, IDC_IBEAM);
|
WIN32_CURSORS.m_ibeam = LoadCursor(nullptr, IDC_IBEAM);
|
||||||
|
WIN32_CURSORS.m_crosshairs = LoadCursor(nullptr, IDC_CROSS);
|
||||||
WIN32_CURSORS.m_wait = LoadCursor(nullptr, IDC_WAIT);
|
WIN32_CURSORS.m_wait = LoadCursor(nullptr, IDC_WAIT);
|
||||||
|
|
||||||
HMODULE dxgilib = LoadLibraryW(L"dxgi.dll");
|
HMODULE dxgilib = LoadLibraryW(L"dxgi.dll");
|
||||||
|
|
|
@ -261,6 +261,7 @@ struct Win32Cursors
|
||||||
HCURSOR m_hResize;
|
HCURSOR m_hResize;
|
||||||
HCURSOR m_vResize;
|
HCURSOR m_vResize;
|
||||||
HCURSOR m_ibeam;
|
HCURSOR m_ibeam;
|
||||||
|
HCURSOR m_crosshairs;
|
||||||
HCURSOR m_wait;
|
HCURSOR m_wait;
|
||||||
};
|
};
|
||||||
namespace boo
|
namespace boo
|
||||||
|
|
|
@ -698,6 +698,8 @@ class WindowWin32 : public IWindow
|
||||||
return WIN32_CURSORS.m_vResize;
|
return WIN32_CURSORS.m_vResize;
|
||||||
case EMouseCursor::IBeam:
|
case EMouseCursor::IBeam:
|
||||||
return WIN32_CURSORS.m_ibeam;
|
return WIN32_CURSORS.m_ibeam;
|
||||||
|
case EMouseCursor::Crosshairs:
|
||||||
|
return WIN32_CURSORS.m_crosshairs;
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
return WIN32_CURSORS.m_arrow;
|
return WIN32_CURSORS.m_arrow;
|
||||||
|
|
|
@ -163,7 +163,7 @@ class ApplicationXlib final : public IApplication
|
||||||
std::unordered_map<Window, IWindow*> m_windows;
|
std::unordered_map<Window, IWindow*> m_windows;
|
||||||
|
|
||||||
Display* m_xDisp = nullptr;
|
Display* m_xDisp = nullptr;
|
||||||
XIM m_xIM;
|
XIM m_xIM = nullptr;
|
||||||
XFontSet m_fontset;
|
XFontSet m_fontset;
|
||||||
XIMStyle m_bestStyle = 0;
|
XIMStyle m_bestStyle = 0;
|
||||||
int m_xDefaultScreen = 0;
|
int m_xDefaultScreen = 0;
|
||||||
|
@ -260,12 +260,8 @@ public:
|
||||||
if (XSetLocaleModifiers("") == nullptr)
|
if (XSetLocaleModifiers("") == nullptr)
|
||||||
Log.report(LogVisor::Warning, "Cannot set locale modifiers.");
|
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;
|
char** missing_charsets;
|
||||||
int num_missing_charsets = 0;
|
int num_missing_charsets = 0;
|
||||||
char* default_string;
|
char* default_string;
|
||||||
|
@ -299,12 +295,14 @@ public:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
XFree(im_supported_styles);
|
XFree(im_supported_styles);
|
||||||
|
}
|
||||||
|
|
||||||
m_xDefaultScreen = DefaultScreen(m_xDisp);
|
m_xDefaultScreen = DefaultScreen(m_xDisp);
|
||||||
X_CURSORS.m_pointer = XCreateFontCursor(m_xDisp, XC_left_ptr);
|
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_hArrow = XCreateFontCursor(m_xDisp, XC_sb_h_double_arrow);
|
||||||
X_CURSORS.m_vArrow = XCreateFontCursor(m_xDisp, XC_sb_v_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_ibeam = XCreateFontCursor(m_xDisp, XC_xterm);
|
||||||
|
X_CURSORS.m_crosshairs = XCreateFontCursor(m_xDisp, XC_cross);
|
||||||
X_CURSORS.m_wait = XCreateFontCursor(m_xDisp, XC_watch);
|
X_CURSORS.m_wait = XCreateFontCursor(m_xDisp, XC_watch);
|
||||||
|
|
||||||
/* The xkb extension requests that the X server does not
|
/* The xkb extension requests that the X server does not
|
||||||
|
|
|
@ -495,11 +495,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
void present()
|
void present()
|
||||||
{
|
{ glXSwapBuffers(m_xDisp, m_glxWindow); }
|
||||||
XLockDisplay(m_xDisp);
|
|
||||||
glXSwapBuffers(m_xDisp, m_glxWindow);
|
|
||||||
XUnlockDisplay(m_xDisp);
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -510,7 +506,7 @@ class WindowXlib : public IWindow
|
||||||
Colormap m_colormapId;
|
Colormap m_colormapId;
|
||||||
Window m_windowId;
|
Window m_windowId;
|
||||||
XIMStyle m_bestStyle;
|
XIMStyle m_bestStyle;
|
||||||
XIC m_xIC;
|
XIC m_xIC = nullptr;
|
||||||
GraphicsContextGLX m_gfxCtx;
|
GraphicsContextGLX m_gfxCtx;
|
||||||
uint32_t m_visualId;
|
uint32_t m_visualId;
|
||||||
|
|
||||||
|
@ -525,7 +521,7 @@ class WindowXlib : public IWindow
|
||||||
double m_vScrollLast = 0.0;
|
double m_vScrollLast = 0.0;
|
||||||
|
|
||||||
/* Cached window rectangle (to avoid repeated X queries) */
|
/* Cached window rectangle (to avoid repeated X queries) */
|
||||||
int m_wx, m_wy, m_ww, m_wh;
|
boo::SWindowRect m_wrect;
|
||||||
float m_pixelFactor;
|
float m_pixelFactor;
|
||||||
bool m_inFs = false;
|
bool m_inFs = false;
|
||||||
|
|
||||||
|
@ -547,6 +543,8 @@ class WindowXlib : public IWindow
|
||||||
return X_CURSORS.m_vArrow;
|
return X_CURSORS.m_vArrow;
|
||||||
case EMouseCursor::IBeam:
|
case EMouseCursor::IBeam:
|
||||||
return X_CURSORS.m_ibeam;
|
return X_CURSORS.m_ibeam;
|
||||||
|
case EMouseCursor::Crosshairs:
|
||||||
|
return X_CURSORS.m_crosshairs;
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
return X_CURSORS.m_pointer;
|
return X_CURSORS.m_pointer;
|
||||||
|
@ -603,6 +601,8 @@ public:
|
||||||
* Now go create an IC using the style we chose.
|
* Now go create an IC using the style we chose.
|
||||||
* Also set the window and fontset attributes now.
|
* Also set the window and fontset attributes now.
|
||||||
*/
|
*/
|
||||||
|
if (xIM)
|
||||||
|
{
|
||||||
XPoint pt = {0,0};
|
XPoint pt = {0,0};
|
||||||
XVaNestedList nlist;
|
XVaNestedList nlist;
|
||||||
m_xIC = XCreateIC(xIM, XNInputStyle, bestInputStyle,
|
m_xIC = XCreateIC(xIM, XNInputStyle, bestInputStyle,
|
||||||
|
@ -614,15 +614,11 @@ public:
|
||||||
nullptr),
|
nullptr),
|
||||||
nullptr);
|
nullptr);
|
||||||
XFree(nlist);
|
XFree(nlist);
|
||||||
if (m_xIC == nullptr)
|
|
||||||
{
|
|
||||||
Log.report(LogVisor::FatalError, "Couldn't create input context.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
long im_event_mask;
|
long im_event_mask;
|
||||||
XGetICValues(m_xIC, XNFilterEvents, &im_event_mask, nullptr);
|
XGetICValues(m_xIC, XNFilterEvents, &im_event_mask, nullptr);
|
||||||
XSelectInput(display, m_windowId, swa.event_mask | im_event_mask);
|
XSelectInput(display, m_windowId, swa.event_mask | im_event_mask);
|
||||||
XSetICFocus(m_xIC);
|
XSetICFocus(m_xIC);
|
||||||
|
}
|
||||||
|
|
||||||
/* The XInput 2.1 extension enables per-pixel smooth scrolling trackpads */
|
/* The XInput 2.1 extension enables per-pixel smooth scrolling trackpads */
|
||||||
XIEventMask mask = {XIAllMasterDevices, XIMaskLen(XI_LASTEVENT)};
|
XIEventMask mask = {XIAllMasterDevices, XIMaskLen(XI_LASTEVENT)};
|
||||||
|
@ -904,6 +900,8 @@ public:
|
||||||
} m_clipData;
|
} m_clipData;
|
||||||
|
|
||||||
void claimKeyboardFocus(const int coord[2])
|
void claimKeyboardFocus(const int coord[2])
|
||||||
|
{
|
||||||
|
if (m_xIC)
|
||||||
{
|
{
|
||||||
XLockDisplay(m_xDisp);
|
XLockDisplay(m_xDisp);
|
||||||
if (!coord)
|
if (!coord)
|
||||||
|
@ -912,14 +910,15 @@ public:
|
||||||
XUnlockDisplay(m_xDisp);
|
XUnlockDisplay(m_xDisp);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
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]);
|
||||||
XPoint pt = {short(coord[0]), short(m_wh - coord[1])};
|
XPoint pt = {short(coord[0]), short(m_wrect.size[1] - coord[1])};
|
||||||
XVaNestedList list = XVaCreateNestedList(0, XNSpotLocation, &pt, nullptr);
|
XVaNestedList list = XVaCreateNestedList(0, XNSpotLocation, &pt, nullptr);
|
||||||
XSetICValues(m_xIC, XNPreeditAttributes, list, nullptr);
|
XSetICValues(m_xIC, XNPreeditAttributes, list, nullptr);
|
||||||
XFree(list);
|
XFree(list);
|
||||||
XSetICFocus(m_xIC);
|
XSetICFocus(m_xIC);
|
||||||
XUnlockDisplay(m_xDisp);
|
XUnlockDisplay(m_xDisp);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool clipboardCopy(EClipboardType type, const uint8_t* data, size_t sz)
|
bool clipboardCopy(EClipboardType type, const uint8_t* data, size_t sz)
|
||||||
{
|
{
|
||||||
|
@ -1108,39 +1107,40 @@ public:
|
||||||
SWindowCoord MakeButtonEventCoord(XEvent* event) const
|
SWindowCoord MakeButtonEventCoord(XEvent* event) const
|
||||||
{
|
{
|
||||||
int x = event->xbutton.x;
|
int x = event->xbutton.x;
|
||||||
int y = m_wh-event->xbutton.y;
|
int y = m_wrect.size[1]-event->xbutton.y;
|
||||||
return
|
return
|
||||||
{
|
{
|
||||||
{x, y},
|
{x, y},
|
||||||
{int(x / m_pixelFactor), int(y / m_pixelFactor)},
|
{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
|
SWindowCoord MakeMotionEventCoord(XEvent* event) const
|
||||||
{
|
{
|
||||||
int x = event->xmotion.x;
|
int x = event->xmotion.x;
|
||||||
int y = m_wh-event->xmotion.y;
|
int y = m_wrect.size[1]-event->xmotion.y;
|
||||||
return
|
return
|
||||||
{
|
{
|
||||||
{x, y},
|
{x, y},
|
||||||
{int(x / m_pixelFactor), int(y / m_pixelFactor)},
|
{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
|
SWindowCoord MakeCrossingEventCoord(XEvent* event) const
|
||||||
{
|
{
|
||||||
int x = event->xcrossing.x;
|
int x = event->xcrossing.x;
|
||||||
int y = m_wh-event->xcrossing.y;
|
int y = m_wrect.size[1]-event->xcrossing.y;
|
||||||
return
|
return
|
||||||
{
|
{
|
||||||
{x, y},
|
{x, y},
|
||||||
{int(x / m_pixelFactor), int(y / m_pixelFactor)},
|
{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
|
/* This procedure sets the application's size constraints and returns
|
||||||
* the IM's preferred size for either the Preedit or Status areas,
|
* the IM's preferred size for either the Preedit or Status areas,
|
||||||
* depending on the value of the name argument. The area argument is
|
* depending on the value of the name argument. The area argument is
|
||||||
|
@ -1167,6 +1167,7 @@ public:
|
||||||
XSetICValues(m_xIC, name, list, nullptr);
|
XSetICValues(m_xIC, name, list, nullptr);
|
||||||
XFree(list);
|
XFree(list);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void _incomingEvent(void* e)
|
void _incomingEvent(void* e)
|
||||||
{
|
{
|
||||||
|
@ -1194,16 +1195,14 @@ public:
|
||||||
int x, y;
|
int x, y;
|
||||||
XTranslateCoordinates(m_xDisp, m_windowId, DefaultRootWindow(m_xDisp), event->xexpose.x, event->xexpose.y, &x, &y, &nw);
|
XTranslateCoordinates(m_xDisp, m_windowId, DefaultRootWindow(m_xDisp), event->xexpose.x, event->xexpose.y, &x, &y, &nw);
|
||||||
XGetWindowAttributes(m_xDisp, m_windowId, &wxa);
|
XGetWindowAttributes(m_xDisp, m_windowId, &wxa);
|
||||||
m_wx = x - wxa.x;
|
m_wrect.location[0] = x - wxa.x;
|
||||||
m_wy = y - wxa.y;
|
m_wrect.location[1] = y - wxa.y;
|
||||||
m_ww = event->xexpose.width;
|
m_wrect.size[0] = event->xexpose.width;
|
||||||
m_wh = event->xexpose.height;
|
m_wrect.size[1] = event->xexpose.height;
|
||||||
if (m_callback)
|
if (m_callback)
|
||||||
{
|
{
|
||||||
SWindowRect rect =
|
|
||||||
{ {m_wx, m_wy}, {m_ww, m_wh} };
|
|
||||||
XUnlockDisplay(m_xDisp);
|
XUnlockDisplay(m_xDisp);
|
||||||
m_callback->resized(rect);
|
m_callback->resized(m_wrect);
|
||||||
XLockDisplay(m_xDisp);
|
XLockDisplay(m_xDisp);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
@ -1215,17 +1214,13 @@ public:
|
||||||
int x, y;
|
int x, y;
|
||||||
XTranslateCoordinates(m_xDisp, m_windowId, DefaultRootWindow(m_xDisp), event->xconfigure.x, event->xconfigure.y, &x, &y, &nw);
|
XTranslateCoordinates(m_xDisp, m_windowId, DefaultRootWindow(m_xDisp), event->xconfigure.x, event->xconfigure.y, &x, &y, &nw);
|
||||||
XGetWindowAttributes(m_xDisp, m_windowId, &wxa);
|
XGetWindowAttributes(m_xDisp, m_windowId, &wxa);
|
||||||
m_wx = x - wxa.x;
|
m_wrect.location[0] = x - wxa.x;
|
||||||
m_wy = y - wxa.y;
|
m_wrect.location[1] = y - wxa.y;
|
||||||
m_ww = event->xconfigure.width;
|
m_wrect.size[0] = event->xconfigure.width;
|
||||||
m_wh = event->xconfigure.height;
|
m_wrect.size[1] = event->xconfigure.height;
|
||||||
|
|
||||||
if (m_callback)
|
if (m_callback)
|
||||||
{
|
m_callback->windowMoved(m_wrect);
|
||||||
SWindowRect rect =
|
|
||||||
{ {m_wx, m_wy}, {m_ww, m_wh} };
|
|
||||||
m_callback->windowMoved(rect);
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
case KeyPress:
|
case KeyPress:
|
||||||
|
@ -1236,14 +1231,17 @@ public:
|
||||||
EModifierKey modifierKey;
|
EModifierKey modifierKey;
|
||||||
unsigned int state = event->xkey.state;
|
unsigned int state = event->xkey.state;
|
||||||
event->xkey.state &= ~ControlMask;
|
event->xkey.state &= ~ControlMask;
|
||||||
std::string utf8Frag = translateUTF8(&event->xkey, m_xIC);
|
|
||||||
ITextInputCallback* inputCb = m_callback->getTextInputCallback();
|
ITextInputCallback* inputCb = m_callback->getTextInputCallback();
|
||||||
|
if (m_xIC)
|
||||||
|
{
|
||||||
|
std::string utf8Frag = translateUTF8(&event->xkey, m_xIC);
|
||||||
if (utf8Frag.size())
|
if (utf8Frag.size())
|
||||||
{
|
{
|
||||||
if (inputCb)
|
if (inputCb)
|
||||||
inputCb->insertText(utf8Frag);
|
inputCb->insertText(utf8Frag);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
char charCode = translateKeysym(&event->xkey, specialKey, modifierKey);
|
char charCode = translateKeysym(&event->xkey, specialKey, modifierKey);
|
||||||
EModifierKey modifierMask = translateModifiers(state);
|
EModifierKey modifierMask = translateModifiers(state);
|
||||||
if (charCode)
|
if (charCode)
|
||||||
|
@ -1283,7 +1281,7 @@ public:
|
||||||
{
|
{
|
||||||
if (m_callback)
|
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);
|
EMouseButton button = translateButton(event->xbutton.button);
|
||||||
if (button != EMouseButton::None)
|
if (button != EMouseButton::None)
|
||||||
{
|
{
|
||||||
|
@ -1318,7 +1316,7 @@ public:
|
||||||
{
|
{
|
||||||
if (m_callback)
|
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);
|
EMouseButton button = translateButton(event->xbutton.button);
|
||||||
if (button != EMouseButton::None)
|
if (button != EMouseButton::None)
|
||||||
{
|
{
|
||||||
|
@ -1345,7 +1343,7 @@ public:
|
||||||
{
|
{
|
||||||
if (m_callback)
|
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));
|
m_callback->mouseMove(MakeMotionEventCoord(event));
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
@ -1354,7 +1352,7 @@ public:
|
||||||
{
|
{
|
||||||
if (m_callback)
|
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));
|
m_callback->mouseEnter(MakeCrossingEventCoord(event));
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
@ -1363,7 +1361,7 @@ public:
|
||||||
{
|
{
|
||||||
if (m_callback)
|
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));
|
m_callback->mouseLeave(MakeCrossingEventCoord(event));
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
@ -1372,7 +1370,7 @@ public:
|
||||||
{
|
{
|
||||||
if (event->xgeneric.extension == XINPUT_OPCODE)
|
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)
|
switch (event->xgeneric.evtype)
|
||||||
{
|
{
|
||||||
case XI_Motion:
|
case XI_Motion:
|
||||||
|
@ -1416,12 +1414,12 @@ public:
|
||||||
if (m_callback && didScroll)
|
if (m_callback && didScroll)
|
||||||
{
|
{
|
||||||
int event_x = int(ev->event_x) >> 16;
|
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 =
|
SWindowCoord coord =
|
||||||
{
|
{
|
||||||
{event_x, event_y},
|
{event_x, event_y},
|
||||||
{int(event_x / m_pixelFactor), int(event_y / m_pixelFactor)},
|
{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);
|
m_callback->scroll(coord, scrollDelta);
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ struct XlibCursors
|
||||||
Cursor m_hArrow;
|
Cursor m_hArrow;
|
||||||
Cursor m_vArrow;
|
Cursor m_vArrow;
|
||||||
Cursor m_ibeam;
|
Cursor m_ibeam;
|
||||||
|
Cursor m_crosshairs;
|
||||||
Cursor m_wait;
|
Cursor m_wait;
|
||||||
};
|
};
|
||||||
extern XlibCursors X_CURSORS;
|
extern XlibCursors X_CURSORS;
|
||||||
|
|
Loading…
Reference in New Issue