New code style refactor

This commit is contained in:
Jack Andersen 2018-12-07 19:17:51 -10:00
parent 2c2c72bfd1
commit 058ea23a00
113 changed files with 23305 additions and 27650 deletions

View File

@ -5,17 +5,13 @@
#include "boo/inputdev/XInputPad.hpp"
#include "boo/inputdev/NintendoPowerA.hpp"
namespace boo
{
namespace boo {
const DeviceSignature BOO_DEVICE_SIGS[] =
{
DEVICE_SIG(DolphinSmashAdapter, 0x57e, 0x337, DeviceType::USB),
const DeviceSignature BOO_DEVICE_SIGS[] = {DEVICE_SIG(DolphinSmashAdapter, 0x57e, 0x337, DeviceType::USB),
DEVICE_SIG(DualshockPad, 0x54c, 0x268, DeviceType::HID),
DEVICE_SIG(GenericPad, 0, 0, DeviceType::HID),
DEVICE_SIG(NintendoPowerA, 0x20D6, 0xA711, DeviceType::USB),
DEVICE_SIG(XInputPad, 0, 0, DeviceType::XInput),
DEVICE_SIG_SENTINEL()
};
DEVICE_SIG_SENTINEL()};
}

View File

@ -4,21 +4,19 @@
#include <mutex>
#include "nxstl/mutex"
namespace boo
{
namespace boo {
class IObj
{
class IObj {
std::atomic_int m_refCount = {0};
protected:
virtual ~IObj() = default;
public:
virtual std::unique_lock<std::recursive_mutex> destructorLock() = 0;
void increment() { m_refCount++; }
void decrement()
{
if (m_refCount.fetch_sub(1) == 1)
{
void decrement() {
if (m_refCount.fetch_sub(1) == 1) {
auto lk = destructorLock();
delete this;
}
@ -26,28 +24,60 @@ public:
};
template <class SubCls>
class ObjToken
{
class ObjToken {
SubCls* m_obj = nullptr;
public:
ObjToken() = default;
ObjToken(SubCls* obj) : m_obj(obj) { if (m_obj) m_obj->increment(); }
ObjToken(const ObjToken& other) : m_obj(other.m_obj) { if (m_obj) m_obj->increment(); }
ObjToken(SubCls* obj) : m_obj(obj) {
if (m_obj)
m_obj->increment();
}
ObjToken(const ObjToken& other) : m_obj(other.m_obj) {
if (m_obj)
m_obj->increment();
}
ObjToken(ObjToken&& other) : m_obj(other.m_obj) { other.m_obj = nullptr; }
ObjToken& operator=(SubCls* obj)
{ if (m_obj) m_obj->decrement(); m_obj = obj; if (m_obj) m_obj->increment(); return *this; }
ObjToken& operator=(const ObjToken& other)
{ if (m_obj) m_obj->decrement(); m_obj = other.m_obj; if (m_obj) m_obj->increment(); return *this; }
ObjToken& operator=(ObjToken&& other)
{ if (m_obj) m_obj->decrement(); m_obj = other.m_obj; other.m_obj = nullptr; return *this; }
~ObjToken() { if (m_obj) m_obj->decrement(); }
ObjToken& operator=(SubCls* obj) {
if (m_obj)
m_obj->decrement();
m_obj = obj;
if (m_obj)
m_obj->increment();
return *this;
}
ObjToken& operator=(const ObjToken& other) {
if (m_obj)
m_obj->decrement();
m_obj = other.m_obj;
if (m_obj)
m_obj->increment();
return *this;
}
ObjToken& operator=(ObjToken&& other) {
if (m_obj)
m_obj->decrement();
m_obj = other.m_obj;
other.m_obj = nullptr;
return *this;
}
~ObjToken() {
if (m_obj)
m_obj->decrement();
}
SubCls* get() const { return m_obj; }
SubCls* operator->() const { return m_obj; }
SubCls& operator*() const { return *m_obj; }
template<class T> T* cast() const { return static_cast<T*>(m_obj); }
template <class T>
T* cast() const {
return static_cast<T*>(m_obj);
}
operator bool() const { return m_obj != nullptr; }
void reset() { if (m_obj) m_obj->decrement(); m_obj = nullptr; }
void reset() {
if (m_obj)
m_obj->decrement();
m_obj = nullptr;
}
};
}
} // namespace boo

View File

@ -5,27 +5,21 @@
#include <condition_variable>
#include "nxstl/condition_variable"
namespace boo
{
namespace boo {
template <class Receiver>
struct DeferredWindowEvents : public IWindowCallback
{
struct DeferredWindowEvents : public IWindowCallback {
Receiver& m_rec;
std::mutex m_mt;
std::condition_variable m_resizeCv;
DeferredWindowEvents(Receiver& rec) : m_rec(rec) {}
bool m_destroyed = false;
void destroyed()
{
m_destroyed = true;
}
void destroyed() { m_destroyed = true; }
bool m_hasResize = false;
SWindowRect m_latestResize;
void resized(const SWindowRect& rect, bool sync)
{
void resized(const SWindowRect& rect, bool sync) {
std::unique_lock<std::mutex> lk(m_mt);
m_latestResize = rect;
m_hasResize = true;
@ -33,10 +27,8 @@ struct DeferredWindowEvents : public IWindowCallback
m_resizeCv.wait_for(lk, std::chrono::milliseconds(500));
}
struct Command
{
enum class Type
{
struct Command {
enum class Type {
MouseDown,
MouseUp,
MouseMove,
@ -64,10 +56,8 @@ struct DeferredWindowEvents : public IWindowCallback
ESpecialKey m_special;
bool m_isRepeat;
void dispatch(Receiver& rec) const
{
switch (m_type)
{
void dispatch(Receiver& rec) const {
switch (m_type) {
case Type::MouseDown:
rec.mouseDown(m_coord, m_button, m_mods);
break;
@ -113,7 +103,8 @@ struct DeferredWindowEvents : public IWindowCallback
case Type::ModKeyUp:
rec.modKeyUp(m_mods);
break;
default: break;
default:
break;
}
}
@ -121,8 +112,7 @@ struct DeferredWindowEvents : public IWindowCallback
};
std::vector<Command> m_cmds;
void mouseDown(const SWindowCoord& coord, EMouseButton button, EModifierKey mods)
{
void mouseDown(const SWindowCoord& coord, EMouseButton button, EModifierKey mods) {
std::unique_lock<std::mutex> lk(m_mt);
m_cmds.emplace_back(Command::Type::MouseDown);
m_cmds.back().m_coord = coord;
@ -130,8 +120,7 @@ struct DeferredWindowEvents : public IWindowCallback
m_cmds.back().m_mods = mods;
}
void mouseUp(const SWindowCoord& coord, EMouseButton button, EModifierKey mods)
{
void mouseUp(const SWindowCoord& coord, EMouseButton button, EModifierKey mods) {
std::unique_lock<std::mutex> lk(m_mt);
m_cmds.emplace_back(Command::Type::MouseUp);
m_cmds.back().m_coord = coord;
@ -139,61 +128,53 @@ struct DeferredWindowEvents : public IWindowCallback
m_cmds.back().m_mods = mods;
}
void mouseMove(const SWindowCoord& coord)
{
void mouseMove(const SWindowCoord& coord) {
std::unique_lock<std::mutex> lk(m_mt);
m_cmds.emplace_back(Command::Type::MouseMove);
m_cmds.back().m_coord = coord;
}
void mouseEnter(const SWindowCoord& coord)
{
void mouseEnter(const SWindowCoord& coord) {
std::unique_lock<std::mutex> lk(m_mt);
m_cmds.emplace_back(Command::Type::MouseEnter);
m_cmds.back().m_coord = coord;
}
void mouseLeave(const SWindowCoord& coord)
{
void mouseLeave(const SWindowCoord& coord) {
std::unique_lock<std::mutex> lk(m_mt);
m_cmds.emplace_back(Command::Type::MouseLeave);
m_cmds.back().m_coord = coord;
}
void scroll(const SWindowCoord& coord, const SScrollDelta& scroll)
{
void scroll(const SWindowCoord& coord, const SScrollDelta& scroll) {
std::unique_lock<std::mutex> lk(m_mt);
m_cmds.emplace_back(Command::Type::Scroll);
m_cmds.back().m_coord = coord;
m_cmds.back().m_scroll = scroll;
}
void touchDown(const STouchCoord& coord, uintptr_t tid)
{
void touchDown(const STouchCoord& coord, uintptr_t tid) {
std::unique_lock<std::mutex> lk(m_mt);
m_cmds.emplace_back(Command::Type::TouchDown);
m_cmds.back().m_tCoord = coord;
m_cmds.back().m_tid = tid;
}
void touchUp(const STouchCoord& coord, uintptr_t tid)
{
void touchUp(const STouchCoord& coord, uintptr_t tid) {
std::unique_lock<std::mutex> lk(m_mt);
m_cmds.emplace_back(Command::Type::TouchUp);
m_cmds.back().m_tCoord = coord;
m_cmds.back().m_tid = tid;
}
void touchMove(const STouchCoord& coord, uintptr_t tid)
{
void touchMove(const STouchCoord& coord, uintptr_t tid) {
std::unique_lock<std::mutex> lk(m_mt);
m_cmds.emplace_back(Command::Type::TouchMove);
m_cmds.back().m_tCoord = coord;
m_cmds.back().m_tid = tid;
}
void charKeyDown(unsigned long charCode, EModifierKey mods, bool isRepeat)
{
void charKeyDown(unsigned long charCode, EModifierKey mods, bool isRepeat) {
std::unique_lock<std::mutex> lk(m_mt);
m_cmds.emplace_back(Command::Type::CharKeyDown);
m_cmds.back().m_charcode = charCode;
@ -201,16 +182,14 @@ struct DeferredWindowEvents : public IWindowCallback
m_cmds.back().m_isRepeat = isRepeat;
}
void charKeyUp(unsigned long charCode, EModifierKey mods)
{
void charKeyUp(unsigned long charCode, EModifierKey mods) {
std::unique_lock<std::mutex> lk(m_mt);
m_cmds.emplace_back(Command::Type::CharKeyUp);
m_cmds.back().m_charcode = charCode;
m_cmds.back().m_mods = mods;
}
void specialKeyDown(ESpecialKey key, EModifierKey mods, bool isRepeat)
{
void specialKeyDown(ESpecialKey key, EModifierKey mods, bool isRepeat) {
std::unique_lock<std::mutex> lk(m_mt);
m_cmds.emplace_back(Command::Type::SpecialKeyDown);
m_cmds.back().m_special = key;
@ -218,24 +197,21 @@ struct DeferredWindowEvents : public IWindowCallback
m_cmds.back().m_isRepeat = isRepeat;
}
void specialKeyUp(ESpecialKey key, EModifierKey mods)
{
void specialKeyUp(ESpecialKey key, EModifierKey mods) {
std::unique_lock<std::mutex> lk(m_mt);
m_cmds.emplace_back(Command::Type::SpecialKeyUp);
m_cmds.back().m_special = key;
m_cmds.back().m_mods = mods;
}
void modKeyDown(EModifierKey mod, bool isRepeat)
{
void modKeyDown(EModifierKey mod, bool isRepeat) {
std::unique_lock<std::mutex> lk(m_mt);
m_cmds.emplace_back(Command::Type::ModKeyDown);
m_cmds.back().m_mods = mod;
m_cmds.back().m_isRepeat = isRepeat;
}
void modKeyUp(EModifierKey mod)
{
void modKeyUp(EModifierKey mod) {
std::unique_lock<std::mutex> lk(m_mt);
m_cmds.emplace_back(Command::Type::ModKeyUp);
m_cmds.back().m_mods = mod;
@ -243,8 +219,7 @@ struct DeferredWindowEvents : public IWindowCallback
ITextInputCallback* getTextInputCallback() { return m_rec.getTextInputCallback(); }
void dispatchEvents()
{
void dispatchEvents() {
std::unique_lock<std::mutex> lk(m_mt);
bool destroyed = m_destroyed;
bool hasResize = m_hasResize;
@ -255,8 +230,7 @@ struct DeferredWindowEvents : public IWindowCallback
m_cmds.swap(cmds);
lk.unlock();
if (destroyed)
{
if (destroyed) {
m_rec.destroyed();
return;
}
@ -269,5 +243,4 @@ struct DeferredWindowEvents : public IWindowCallback
}
};
}
} // namespace boo

View File

@ -7,29 +7,26 @@
#include "IWindow.hpp"
#include "inputdev/DeviceFinder.hpp"
namespace boo
{
namespace boo {
class IApplication;
struct IApplicationCallback
{
struct IApplicationCallback {
virtual int appMain(IApplication*) = 0;
virtual void appQuitting(IApplication*) = 0;
virtual void appFilesOpen(IApplication*, const std::vector<SystemString>&) {}
};
class IApplication
{
class IApplication {
friend class WindowCocoa;
friend class WindowWayland;
friend class WindowXlib;
friend class WindowWin32;
virtual void _deletedWindow(IWindow* window) = 0;
public:
virtual ~IApplication() = default;
enum class EPlatformType
{
enum class EPlatformType {
Auto = 0,
Wayland = 1,
Xlib = 2,
@ -55,40 +52,23 @@ public:
virtual std::shared_ptr<IWindow> newWindow(SystemStringView title) = 0;
};
int
ApplicationRun(IApplication::EPlatformType platform,
IApplicationCallback& cb,
SystemStringView uniqueName,
SystemStringView friendlyName,
SystemStringView pname,
const std::vector<SystemString>& args,
std::string_view gfxApi = {},
uint32_t samples = 1,
uint32_t anisotropy = 1,
bool deepColor = false,
int ApplicationRun(IApplication::EPlatformType platform, IApplicationCallback& cb, SystemStringView uniqueName,
SystemStringView friendlyName, SystemStringView pname, const std::vector<SystemString>& args,
std::string_view gfxApi = {}, uint32_t samples = 1, uint32_t anisotropy = 1, bool deepColor = false,
bool singleInstance = true);
extern IApplication* APP;
static inline int
ApplicationRun(IApplication::EPlatformType platform,
IApplicationCallback& cb,
SystemStringView uniqueName,
SystemStringView friendlyName,
int argc, const SystemChar** argv,
std::string_view gfxApi = {},
uint32_t samples = 1,
uint32_t anisotropy = 1,
bool deepColor = false,
bool singleInstance=true)
{
static inline int ApplicationRun(IApplication::EPlatformType platform, IApplicationCallback& cb,
SystemStringView uniqueName, SystemStringView friendlyName, int argc,
const SystemChar** argv, std::string_view gfxApi = {}, uint32_t samples = 1,
uint32_t anisotropy = 1, bool deepColor = false, bool singleInstance = true) {
if (APP)
return 1;
std::vector<SystemString> args;
for (int i = 1; i < argc; ++i)
args.push_back(argv[i]);
return ApplicationRun(platform, cb, uniqueName, friendlyName, argv[0], args,
gfxApi, samples, anisotropy, deepColor, singleInstance);
}
return ApplicationRun(platform, cb, uniqueName, friendlyName, argv[0], args, gfxApi, samples, anisotropy, deepColor,
singleInstance);
}
} // namespace boo

View File

@ -3,21 +3,17 @@
#include <memory>
#include <cstdint>
namespace boo
{
namespace boo {
struct IGraphicsCommandQueue;
struct IGraphicsDataFactory;
class IGraphicsContext
{
class IGraphicsContext {
friend class WindowCocoa;
friend class WindowXCB;
virtual void _setCallback(class IWindowCallback* cb) { (void)cb; }
public:
enum class EGraphicsAPI
{
enum class EGraphicsAPI {
None = 0,
OpenGL3_3 = 1,
OpenGL4_2 = 2,
@ -29,8 +25,7 @@ public:
NX = 9
};
enum class EPixelFormat
{
enum class EPixelFormat {
None = 0,
RGBA8 = 1, /* Default */
RGBA16 = 2,
@ -59,5 +54,4 @@ public:
virtual IGraphicsDataFactory* getLoadContextDataFactory() = 0;
};
}
} // namespace boo

View File

@ -8,66 +8,46 @@
#undef min
#undef max
namespace boo
{
namespace boo {
struct IGraphicsCommandQueue;
struct IGraphicsDataFactory;
struct IAudioVoiceEngine;
enum class EMouseButton
{
None = 0,
Primary = 1,
Secondary = 2,
Middle = 3,
Aux1 = 4,
Aux2 = 5
};
enum class EMouseButton { None = 0, Primary = 1, Secondary = 2, Middle = 3, Aux1 = 4, Aux2 = 5 };
struct SWindowCoord
{
struct SWindowCoord {
int pixel[2];
int virtualPixel[2];
float norm[2];
};
struct SWindowRect
{
struct SWindowRect {
int location[2];
int size[2];
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) {
location[0] = x;
location[1] = y;
size[0] = w;
size[1] = h;
}
bool operator!=(const SWindowRect& other) const
{
return location[0] != other.location[0] ||
location[1] != other.location[1] ||
size[0] != other.size[0] ||
bool operator!=(const SWindowRect& other) const {
return location[0] != other.location[0] || location[1] != other.location[1] || size[0] != other.size[0] ||
size[1] != other.size[1];
}
bool operator==(const SWindowRect& other) const { return !(*this != other); }
bool coordInRect(const SWindowCoord& coord) const
{
return coord.pixel[0] >= location[0] && coord.pixel[0] < location[0] + size[0] &&
coord.pixel[1] >= location[1] && coord.pixel[1] < location[1] + size[1];
bool coordInRect(const SWindowCoord& coord) const {
return coord.pixel[0] >= location[0] && coord.pixel[0] < location[0] + size[0] && coord.pixel[1] >= location[1] &&
coord.pixel[1] < location[1] + size[1];
}
SWindowRect intersect(const SWindowRect& other) const
{
if (location[0] < other.location[0] + other.size[0] &&
location[0] + size[0] > other.location[0] &&
location[1] < other.location[1] + other.size[1] &&
location[1] + size[1] > other.location[1])
{
SWindowRect intersect(const SWindowRect& other) const {
if (location[0] < other.location[0] + other.size[0] && location[0] + size[0] > other.location[0] &&
location[1] < other.location[1] + other.size[1] && location[1] + size[1] > other.location[1]) {
SWindowRect ret;
ret.location[0] = std::max(location[0], other.location[0]);
ret.location[1] = std::max(location[1], other.location[1]);
@ -79,19 +59,16 @@ struct SWindowRect
}
};
struct STouchCoord
{
struct STouchCoord {
double coord[2];
};
struct SScrollDelta
{
struct SScrollDelta {
double delta[2];
bool isFine; /* Use system-scale fine-scroll (for scrollable-trackpads) */
bool isAccelerated = false; /* System performs acceleration computation */
SScrollDelta operator+(const SScrollDelta& other)
{
SScrollDelta operator+(const SScrollDelta& other) {
SScrollDelta ret;
ret.delta[0] = delta[0] + other.delta[0];
ret.delta[1] = delta[1] + other.delta[1];
@ -99,19 +76,20 @@ struct SScrollDelta
ret.isAccelerated = isAccelerated || other.isAccelerated;
return ret;
}
SScrollDelta& operator+=(const SScrollDelta& other)
{
SScrollDelta& operator+=(const SScrollDelta& other) {
delta[0] += other.delta[0];
delta[1] += other.delta[1];
isFine |= other.isFine;
isAccelerated |= other.isAccelerated;
return *this;
}
void zeroOut() {delta[0] = 0.0; delta[1] = 0.0;}
void zeroOut() {
delta[0] = 0.0;
delta[1] = 0.0;
}
};
enum class ESpecialKey
{
enum class ESpecialKey {
None = 0,
F1 = 1,
F2 = 2,
@ -140,8 +118,7 @@ enum class ESpecialKey
Down = 25
};
enum class EModifierKey
{
enum class EModifierKey {
None = 0,
Ctrl = 1 << 0,
Alt = 1 << 2,
@ -151,81 +128,91 @@ enum class EModifierKey
};
ENABLE_BITWISE_ENUM(EModifierKey)
struct ITextInputCallback
{
struct ITextInputCallback {
virtual bool hasMarkedText() const = 0;
virtual std::pair<int, int> markedRange() const = 0;
virtual std::pair<int, int> selectedRange() const = 0;
virtual void setMarkedText(std::string_view str,
const std::pair<int,int>& selectedRange,
virtual void setMarkedText(std::string_view str, const std::pair<int, int>& selectedRange,
const std::pair<int, int>& replacementRange) = 0;
virtual void unmarkText() = 0;
virtual std::string substringForRange(const std::pair<int,int>& range,
std::pair<int,int>& actualRange) const=0;
virtual std::string substringForRange(const std::pair<int, int>& range, std::pair<int, int>& actualRange) const = 0;
virtual void insertText(std::string_view str, const std::pair<int, int>& range = {-1, 0}) = 0;
virtual int characterIndexAtPoint(const SWindowCoord& point) const = 0;
virtual SWindowRect rectForCharacterRange(const std::pair<int, int>& range,
std::pair<int, int>& actualRange) const = 0;
};
class IWindowCallback
{
class IWindowCallback {
public:
virtual void resized(const SWindowRect& rect, bool sync)
{(void)rect;}
virtual void mouseDown(const SWindowCoord& coord, EMouseButton button, EModifierKey mods)
{(void)coord;(void)button;(void)mods;}
virtual void mouseUp(const SWindowCoord& coord, EMouseButton button, EModifierKey mods)
{(void)coord;(void)button;(void)mods;}
virtual void mouseMove(const SWindowCoord& coord)
{(void)coord;}
virtual void mouseEnter(const SWindowCoord& coord)
{(void)coord;}
virtual void mouseLeave(const SWindowCoord& coord)
{(void)coord;}
virtual void scroll(const SWindowCoord& coord, const SScrollDelta& scroll)
{(void)coord;(void)scroll;}
virtual void resized(const SWindowRect& rect, bool sync) { (void)rect; }
virtual void mouseDown(const SWindowCoord& coord, EMouseButton button, EModifierKey mods) {
(void)coord;
(void)button;
(void)mods;
}
virtual void mouseUp(const SWindowCoord& coord, EMouseButton button, EModifierKey mods) {
(void)coord;
(void)button;
(void)mods;
}
virtual void mouseMove(const SWindowCoord& coord) { (void)coord; }
virtual void mouseEnter(const SWindowCoord& coord) { (void)coord; }
virtual void mouseLeave(const SWindowCoord& coord) { (void)coord; }
virtual void scroll(const SWindowCoord& coord, const SScrollDelta& scroll) {
(void)coord;
(void)scroll;
}
virtual void touchDown(const STouchCoord& coord, uintptr_t tid)
{(void)coord;(void)tid;}
virtual void touchUp(const STouchCoord& coord, uintptr_t tid)
{(void)coord;(void)tid;}
virtual void touchMove(const STouchCoord& coord, uintptr_t tid)
{(void)coord;(void)tid;}
virtual void touchDown(const STouchCoord& coord, uintptr_t tid) {
(void)coord;
(void)tid;
}
virtual void touchUp(const STouchCoord& coord, uintptr_t tid) {
(void)coord;
(void)tid;
}
virtual void touchMove(const STouchCoord& coord, uintptr_t tid) {
(void)coord;
(void)tid;
}
virtual void charKeyDown(unsigned long charCode, EModifierKey mods, bool isRepeat)
{(void)charCode;(void)mods;(void)isRepeat;}
virtual void charKeyUp(unsigned long charCode, EModifierKey mods)
{(void)charCode;(void)mods;}
virtual void specialKeyDown(ESpecialKey key, EModifierKey mods, bool isRepeat)
{(void)key;(void)mods;(void)isRepeat;}
virtual void specialKeyUp(ESpecialKey key, EModifierKey mods)
{(void)key;(void)mods;}
virtual void modKeyDown(EModifierKey mod, bool isRepeat)
{(void)mod;(void)isRepeat;}
virtual void charKeyDown(unsigned long charCode, EModifierKey mods, bool isRepeat) {
(void)charCode;
(void)mods;
(void)isRepeat;
}
virtual void charKeyUp(unsigned long charCode, EModifierKey mods) {
(void)charCode;
(void)mods;
}
virtual void specialKeyDown(ESpecialKey key, EModifierKey mods, bool isRepeat) {
(void)key;
(void)mods;
(void)isRepeat;
}
virtual void specialKeyUp(ESpecialKey key, EModifierKey mods) {
(void)key;
(void)mods;
}
virtual void modKeyDown(EModifierKey mod, bool isRepeat) {
(void)mod;
(void)isRepeat;
}
virtual void modKeyUp(EModifierKey mod) { (void)mod; }
virtual ITextInputCallback* getTextInputCallback() { return nullptr; }
virtual void focusLost() {}
virtual void focusGained() {}
virtual void windowMoved(const SWindowRect& rect)
{ (void)rect; }
virtual void windowMoved(const SWindowRect& rect) { (void)rect; }
virtual void destroyed()
{}
virtual void destroyed() {}
};
enum class ETouchType
{
None = 0,
Display = 1,
Trackpad = 2
};
enum class ETouchType { None = 0, Display = 1, Trackpad = 2 };
enum class EWindowStyle
{
enum class EWindowStyle {
None = 0,
Titlebar = 1 << 0,
Resize = 1 << 1,
@ -235,28 +222,12 @@ enum class EWindowStyle
};
ENABLE_BITWISE_ENUM(EWindowStyle)
enum class EMouseCursor
{
None = 0,
Pointer = 1,
HorizontalArrow = 2,
VerticalArrow = 3,
IBeam = 4,
Crosshairs = 5
};
enum class EMouseCursor { None = 0, Pointer = 1, HorizontalArrow = 2, VerticalArrow = 3, IBeam = 4, Crosshairs = 5 };
enum class EClipboardType
{
None = 0,
String = 1,
UTF8String = 2,
PNGImage = 3
};
enum class EClipboardType { None = 0, String = 1, UTF8String = 2, PNGImage = 3 };
class IWindow : public std::enable_shared_from_this<IWindow>
{
class IWindow : public std::enable_shared_from_this<IWindow> {
public:
virtual ~IWindow() = default;
virtual void setCallback(IWindowCallback* cb) = 0;
@ -274,16 +245,14 @@ public:
virtual void setWindowFrameDefault() = 0;
virtual void getWindowFrame(float& xOut, float& yOut, float& wOut, float& hOut) const = 0;
virtual void getWindowFrame(int& xOut, int& yOut, int& wOut, int& hOut) const = 0;
virtual SWindowRect getWindowFrame() const
{
virtual SWindowRect getWindowFrame() const {
SWindowRect retval;
getWindowFrame(retval.location[0], retval.location[1], retval.size[0], retval.size[1]);
return retval;
}
virtual void setWindowFrame(float x, float y, float w, float h) = 0;
virtual void setWindowFrame(int x, int y, int w, int h) = 0;
virtual void setWindowFrame(const SWindowRect& rect)
{
virtual void setWindowFrame(const SWindowRect& rect) {
setWindowFrame(rect.location[0], rect.location[1], rect.size[0], rect.size[1]);
}
virtual float getVirtualPixelFactor() const = 0;
@ -298,7 +267,10 @@ public:
virtual void waitForRetrace() = 0;
virtual uintptr_t getPlatformHandle() const = 0;
virtual bool _incomingEvent(void* event) {(void)event; return false;}
virtual bool _incomingEvent(void* event) {
(void)event;
return false;
}
virtual void _cleanup() {}
virtual ETouchType getTouchType() const = 0;
@ -318,5 +290,4 @@ public:
virtual IGraphicsDataFactory* getLoadContextDataFactory() = 0;
};
}
} // namespace boo

View File

@ -14,8 +14,9 @@
template <class T>
using ComPtr = Microsoft::WRL::ComPtr<T>;
template <class T>
static inline ComPtr<T>* ReferenceComPtr(ComPtr<T>& ptr)
{ return reinterpret_cast<ComPtr<T>*>(ptr.GetAddressOf()); }
static inline ComPtr<T>* ReferenceComPtr(ComPtr<T>& ptr) {
return reinterpret_cast<ComPtr<T>*>(ptr.GetAddressOf());
}
#endif
#include <string>
@ -23,37 +24,31 @@ static inline ComPtr<T>* ReferenceComPtr(ComPtr<T>& ptr)
#ifndef ENABLE_BITWISE_ENUM
#define ENABLE_BITWISE_ENUM(type) \
constexpr type operator|(type a, type b)\
{\
constexpr type operator|(type a, type b) { \
using T = std::underlying_type_t<type>; \
return type(static_cast<T>(a) | static_cast<T>(b)); \
} \
constexpr type operator&(type a, type b)\
{\
constexpr type operator&(type a, type b) { \
using T = std::underlying_type_t<type>; \
return type(static_cast<T>(a) & static_cast<T>(b)); \
} \
inline type& operator|=(type& a, const type& b)\
{\
inline type& operator|=(type& a, const type& b) { \
using T = std::underlying_type_t<type>; \
a = type(static_cast<T>(a) | static_cast<T>(b)); \
return a; \
} \
inline type& operator&=(type& a, const type& b)\
{\
inline type& operator&=(type& a, const type& b) { \
using T = std::underlying_type_t<type>; \
a = type(static_cast<T>(a) & static_cast<T>(b)); \
return a; \
} \
inline type operator~(const type& key)\
{\
inline type operator~(const type& key) { \
using T = std::underlying_type_t<type>; \
return type(~static_cast<T>(key)); \
}
#endif
namespace boo
{
namespace boo {
#ifdef _WIN32
using SystemString = std::wstring;
@ -75,7 +70,9 @@ namespace boo
#define __BooTraceArgs , const char *file, int line
#define __BooTraceArgsUse , file, line
#define __BooTraceInitializer , m_file(file), m_line(line)
#define __BooTraceFields const char* m_file; int m_line;
#define __BooTraceFields \
const char* m_file; \
int m_line;
#define BooTrace , __FILE__, __LINE__
#else
#define __BooTraceArgs
@ -85,5 +82,4 @@ namespace boo
#define BooTrace
#endif
}
} // namespace boo

View File

@ -9,10 +9,10 @@
/** Multiplatform TLS-pointer wrapper (for compilers without proper thread_local support) */
template <class T>
class ThreadLocalPtr
{
class ThreadLocalPtr {
#if _WIN32
DWORD m_key;
public:
ThreadLocalPtr() { m_key = TlsAlloc(); }
~ThreadLocalPtr() { TlsFree(m_key); }
@ -20,6 +20,7 @@ public:
void reset(T* v = nullptr) { TlsSetValue(m_key, LPVOID(v)); }
#else
pthread_key_t m_key;
public:
ThreadLocalPtr() { pthread_key_create(&m_key, nullptr); }
~ThreadLocalPtr() { pthread_key_delete(m_key); }
@ -30,4 +31,3 @@ public:
};
#endif

View File

@ -2,24 +2,19 @@
#include "IApplication.hpp"
namespace boo
{
namespace boo {
#if WINDOWS_STORE
using namespace Windows::ApplicationModel::Core;
ref struct ViewProvider sealed : IFrameworkViewSource
{
internal:
ViewProvider(boo::IApplicationCallback& appCb,
SystemStringView uniqueName,
SystemStringView friendlyName,
SystemStringView pname,
Platform::Array<Platform::String^>^ params,
bool singleInstance)
: m_appCb(appCb), m_uniqueName(uniqueName), m_friendlyName(friendlyName),
m_pname(pname), m_singleInstance(singleInstance)
{
ref struct ViewProvider sealed : IFrameworkViewSource {
internal : ViewProvider(boo::IApplicationCallback& appCb, SystemStringView uniqueName, SystemStringView friendlyName,
SystemStringView pname, Platform::Array<Platform::String ^> ^ params, bool singleInstance)
: m_appCb(appCb)
, m_uniqueName(uniqueName)
, m_friendlyName(friendlyName)
, m_pname(pname)
, m_singleInstance(singleInstance) {
SystemChar selfPath[1024];
GetModuleFileNameW(nullptr, selfPath, 1024);
m_args.reserve(params->Length + 1);
@ -27,11 +22,11 @@ internal:
for (Platform::String ^ str : params)
m_args.emplace_back(str->Data());
}
public:
virtual IFrameworkView ^ CreateView();
internal:
boo::IApplicationCallback& m_appCb;
internal : boo::IApplicationCallback& m_appCb;
SystemString m_uniqueName;
SystemString m_friendlyName;
SystemString m_pname;
@ -40,5 +35,4 @@ internal:
};
#endif
}
} // namespace boo

View File

@ -5,22 +5,15 @@
#include <memory>
#include "boo/BooObject.hpp"
namespace boo
{
namespace boo {
struct IAudioVoice;
struct IAudioVoiceCallback;
struct ChannelMap;
struct IAudioSubmixCallback;
enum class SubmixFormat
{
Int16,
Int32,
Float
};
enum class SubmixFormat { Int16, Int32, Float };
struct IAudioSubmix : IObj
{
struct IAudioSubmix : IObj {
/** Reset channel-levels to silence; unbind all submixes */
virtual void resetSendLevels() = 0;
@ -34,22 +27,17 @@ struct IAudioSubmix : IObj
virtual SubmixFormat getSampleFormat() const = 0;
};
struct IAudioSubmixCallback
{
struct IAudioSubmixCallback {
/** Client-provided claim to implement / is ready to call applyEffect() */
virtual bool canApplyEffect() const = 0;
/** Client-provided effect solution for interleaved, master sample-rate audio */
virtual void applyEffect(int16_t* audio, size_t frameCount,
const ChannelMap& chanMap, double sampleRate) const=0;
virtual void applyEffect(int32_t* audio, size_t frameCount,
const ChannelMap& chanMap, double sampleRate) const=0;
virtual void applyEffect(float* audio, size_t frameCount,
const ChannelMap& chanMap, double sampleRate) const=0;
virtual void applyEffect(int16_t* audio, size_t frameCount, const ChannelMap& chanMap, double sampleRate) const = 0;
virtual void applyEffect(int32_t* audio, size_t frameCount, const ChannelMap& chanMap, double sampleRate) const = 0;
virtual void applyEffect(float* audio, size_t frameCount, const ChannelMap& chanMap, double sampleRate) const = 0;
/** Notify of output sample rate changes (for instance, changing the default audio device on Windows) */
virtual void resetOutputSampleRate(double sampleRate) = 0;
};
}
} // namespace boo

View File

@ -5,21 +5,12 @@
#include <cstring>
#include "boo/BooObject.hpp"
namespace boo
{
namespace boo {
struct IAudioSubmix;
enum class AudioChannelSet
{
Stereo,
Quad,
Surround51,
Surround71,
Unknown = 0xff
};
enum class AudioChannelSet { Stereo, Quad, Surround51, Surround71, Unknown = 0xff };
enum class AudioChannel
{
enum class AudioChannel {
FrontLeft,
FrontRight,
RearLeft,
@ -31,16 +22,13 @@ enum class AudioChannel
Unknown = 0xff
};
struct ChannelMap
{
struct ChannelMap {
unsigned m_channelCount = 0;
AudioChannel m_channels[8] = {};
};
static inline unsigned ChannelCount(AudioChannelSet layout)
{
switch (layout)
{
static inline unsigned ChannelCount(AudioChannelSet layout) {
switch (layout) {
case AudioChannelSet::Stereo:
return 2;
case AudioChannelSet::Quad:
@ -49,13 +37,13 @@ static inline unsigned ChannelCount(AudioChannelSet layout)
return 6;
case AudioChannelSet::Surround71:
return 8;
default: break;
default:
break;
}
return 0;
}
struct IAudioVoice : IObj
{
struct IAudioVoice : IObj {
/** Set sample rate into voice (may result in audio discontinuities) */
virtual void resetSampleRate(double sampleRate) = 0;
@ -78,8 +66,7 @@ struct IAudioVoice : IObj
virtual void stop() = 0;
};
struct IAudioVoiceCallback
{
struct IAudioVoiceCallback {
/** boo calls this on behalf of the audio platform to proactively invoke potential
* pitch or panning changes before processing samples */
virtual void preSupplyAudio(boo::IAudioVoice& voice, double dt) = 0;
@ -90,21 +77,17 @@ struct IAudioVoiceCallback
/** after resampling, boo calls this for each submix that this voice targets;
* client performs volume processing and bus-routing this way */
virtual void routeAudio(size_t frames, size_t channels, double dt, int busId, int16_t* in, int16_t* out)
{
virtual void routeAudio(size_t frames, size_t channels, double dt, int busId, int16_t* in, int16_t* out) {
memmove(out, in, frames * channels * 2);
}
virtual void routeAudio(size_t frames, size_t channels, double dt, int busId, int32_t* in, int32_t* out)
{
virtual void routeAudio(size_t frames, size_t channels, double dt, int busId, int32_t* in, int32_t* out) {
memmove(out, in, frames * channels * 4);
}
virtual void routeAudio(size_t frames, size_t channels, double dt, int busId, float* in, float* out)
{
virtual void routeAudio(size_t frames, size_t channels, double dt, int busId, float* in, float* out) {
memmove(out, in, frames * channels * 4);
}
};
}
} // namespace boo

View File

@ -7,13 +7,11 @@
#include <memory>
#include <vector>
namespace boo
{
namespace boo {
struct IAudioVoiceEngine;
/** Time-sensitive event callback for synchronizing the client with rendered audio waveform */
struct IAudioVoiceEngineCallback
{
struct IAudioVoiceEngineCallback {
/** All mixing occurs in virtual 5ms intervals;
* this is called at the start of each interval for all mixable entities */
virtual void on5MsInterval(IAudioVoiceEngine& engine, double dt) {}
@ -25,8 +23,7 @@ struct IAudioVoiceEngineCallback
/** Mixing and sample-rate-conversion system. Allocates voices and mixes them
* before sending the final samples to an OS-supplied audio-queue */
struct IAudioVoiceEngine
{
struct IAudioVoiceEngine {
virtual ~IAudioVoiceEngine() = default;
/** Client calls this to request allocation of new mixer-voice.
@ -36,13 +33,11 @@ struct IAudioVoiceEngine
* Client must be prepared to supply audio frames via the callback when this is called;
* the backing audio-buffers are primed with initial data for low-latency playback start
*/
virtual ObjToken<IAudioVoice> allocateNewMonoVoice(double sampleRate,
IAudioVoiceCallback* cb,
virtual ObjToken<IAudioVoice> allocateNewMonoVoice(double sampleRate, IAudioVoiceCallback* cb,
bool dynamicPitch = false) = 0;
/** Same as allocateNewMonoVoice, but source audio is stereo-interleaved */
virtual ObjToken<IAudioVoice> allocateNewStereoVoice(double sampleRate,
IAudioVoiceCallback* cb,
virtual ObjToken<IAudioVoice> allocateNewStereoVoice(double sampleRate, IAudioVoiceCallback* cb,
bool dynamicPitch = false) = 0;
/** Client calls this to allocate a Submix for gathering audio together for effects processing */
@ -112,5 +107,4 @@ std::unique_ptr<IAudioVoiceEngine> NewWAVAudioVoiceEngine(const char* path, doub
std::unique_ptr<IAudioVoiceEngine> NewWAVAudioVoiceEngine(const wchar_t* path, double sampleRate, int numChans);
#endif
}
} // namespace boo

View File

@ -5,17 +5,17 @@
#include <vector>
#include <cstdint>
namespace boo
{
namespace boo {
struct IAudioVoiceEngine;
using ReceiveFunctor = std::function<void(std::vector<uint8_t>&&, double time)>;
class IMIDIPort
{
class IMIDIPort {
bool m_virtual;
protected:
IAudioVoiceEngine* m_parent;
IMIDIPort(IAudioVoiceEngine* parent, bool virt) : m_virtual(virt), m_parent(parent) {}
public:
virtual ~IMIDIPort();
bool isVirtual() const { return m_virtual; }
@ -23,40 +23,38 @@ public:
void _disown() { m_parent = nullptr; }
};
class IMIDIReceiver
{
class IMIDIReceiver {
public:
ReceiveFunctor m_receiver;
IMIDIReceiver(ReceiveFunctor&& receiver) : m_receiver(std::move(receiver)) {}
};
class IMIDIIn : public IMIDIPort, public IMIDIReceiver
{
class IMIDIIn : public IMIDIPort, public IMIDIReceiver {
protected:
IMIDIIn(IAudioVoiceEngine* parent, bool virt, ReceiveFunctor&& receiver)
: IMIDIPort(parent, virt), IMIDIReceiver(std::move(receiver)) {}
public:
virtual ~IMIDIIn();
};
class IMIDIOut : public IMIDIPort
{
class IMIDIOut : public IMIDIPort {
protected:
IMIDIOut(IAudioVoiceEngine* parent, bool virt) : IMIDIPort(parent, virt) {}
public:
virtual ~IMIDIOut();
virtual size_t send(const void* buf, size_t len) const = 0;
};
class IMIDIInOut : public IMIDIPort, public IMIDIReceiver
{
class IMIDIInOut : public IMIDIPort, public IMIDIReceiver {
protected:
IMIDIInOut(IAudioVoiceEngine* parent, bool virt, ReceiveFunctor&& receiver)
: IMIDIPort(parent, virt), IMIDIReceiver(std::move(receiver)) {}
public:
virtual ~IMIDIInOut();
virtual size_t send(const void* buf, size_t len) const = 0;
};
}
} // namespace boo

View File

@ -3,11 +3,9 @@
#include <cstdlib>
#include <cstdint>
namespace boo
{
namespace boo {
class IMIDIReader
{
class IMIDIReader {
public:
virtual void noteOff(uint8_t chan, uint8_t key, uint8_t velocity) = 0;
virtual void noteOn(uint8_t chan, uint8_t key, uint8_t velocity) = 0;
@ -37,5 +35,4 @@ public:
virtual void reset() = 0;
};
}
} // namespace boo

View File

@ -5,22 +5,18 @@
#include <functional>
#include <vector>
namespace boo
{
namespace boo {
class MIDIDecoder
{
class MIDIDecoder {
IMIDIReader& m_out;
uint8_t m_status = 0;
bool _readContinuedValue(std::vector<uint8_t>::const_iterator& it,
std::vector<uint8_t>::const_iterator end,
bool _readContinuedValue(std::vector<uint8_t>::const_iterator& it, std::vector<uint8_t>::const_iterator end,
uint32_t& valOut);
public:
MIDIDecoder(IMIDIReader& out) : m_out(out) {}
std::vector<uint8_t>::const_iterator
receiveBytes(std::vector<uint8_t>::const_iterator begin,
std::vector<uint8_t>::const_iterator receiveBytes(std::vector<uint8_t>::const_iterator begin,
std::vector<uint8_t>::const_iterator end);
};
}
} // namespace boo

View File

@ -3,16 +3,15 @@
#include "boo/audiodev/IMIDIReader.hpp"
#include "boo/audiodev/IMIDIPort.hpp"
namespace boo
{
namespace boo {
template <class Sender>
class MIDIEncoder : public IMIDIReader
{
class MIDIEncoder : public IMIDIReader {
Sender& m_sender;
uint8_t m_status = 0;
void _sendMessage(const uint8_t* data, size_t len);
void _sendContinuedValue(uint32_t val);
public:
MIDIEncoder(Sender& sender) : m_sender(sender) {}
@ -44,5 +43,4 @@ public:
void reset();
};
}
} // namespace boo

View File

@ -10,4 +10,3 @@
#include "graphicsdev/IGraphicsCommandQueue.hpp"
#include "graphicsdev/IGraphicsDataFactory.hpp"
#include "DeferredWindowEvents.hpp"

View File

@ -9,30 +9,26 @@
#include <vector>
#include <unordered_set>
typedef HRESULT (WINAPI *pD3DCreateBlob)
(SIZE_T Size,
ID3DBlob** ppBlob);
typedef HRESULT(WINAPI* pD3DCreateBlob)(SIZE_T Size, ID3DBlob** ppBlob);
extern pD3DCreateBlob D3DCreateBlobPROC;
namespace boo
{
namespace boo {
struct BaseGraphicsData;
class D3D11DataFactory : public IGraphicsDataFactory
{
class D3D11DataFactory : public IGraphicsDataFactory {
public:
virtual ~D3D11DataFactory() = default;
Platform platform() const { return Platform::D3D11; }
const SystemChar* platformName() const { return _SYS_STR("D3D11"); }
class Context final : public IGraphicsDataFactory::Context
{
class Context final : public IGraphicsDataFactory::Context {
friend class D3D11DataFactoryImpl;
D3D11DataFactory& m_parent;
boo::ObjToken<BaseGraphicsData> m_data;
Context(D3D11DataFactory& parent __BooTraceArgs);
~Context();
public:
Platform platform() const { return Platform::D3D11; }
const SystemChar* platformName() const { return _SYS_STR("D3D11"); }
@ -43,36 +39,31 @@ public:
boo::ObjToken<ITextureS> newStaticTexture(size_t width, size_t height, size_t mips, TextureFormat fmt,
TextureClampMode clampMode, const void* data, size_t sz);
boo::ObjToken<ITextureSA> newStaticArrayTexture(size_t width, size_t height, size_t layers, size_t mips,
TextureFormat fmt, TextureClampMode clampMode,
const void* data, size_t sz);
boo::ObjToken<ITextureD> newDynamicTexture(size_t width, size_t height, TextureFormat fmt, TextureClampMode clampMode);
TextureFormat fmt, TextureClampMode clampMode, const void* data,
size_t sz);
boo::ObjToken<ITextureD> newDynamicTexture(size_t width, size_t height, TextureFormat fmt,
TextureClampMode clampMode);
boo::ObjToken<ITextureR> newRenderTexture(size_t width, size_t height, TextureClampMode clampMode,
size_t colorBindCount, size_t depthBindCount);
ObjToken<IShaderStage>
newShaderStage(const uint8_t* data, size_t size, PipelineStage stage);
ObjToken<IShaderStage> newShaderStage(const uint8_t* data, size_t size, PipelineStage stage);
ObjToken<IShaderPipeline>
newShaderPipeline(ObjToken<IShaderStage> vertex, ObjToken<IShaderStage> fragment,
ObjToken<IShaderPipeline> newShaderPipeline(ObjToken<IShaderStage> vertex, ObjToken<IShaderStage> fragment,
ObjToken<IShaderStage> geometry, ObjToken<IShaderStage> control,
ObjToken<IShaderStage> evaluation, const VertexFormatInfo& vtxFmt,
const AdditionalPipelineInfo& additionalInfo);
boo::ObjToken<IShaderDataBinding>
newShaderDataBinding(const boo::ObjToken<IShaderPipeline>& pipeline,
const boo::ObjToken<IGraphicsBuffer>& vbo,
const boo::ObjToken<IGraphicsBuffer>& instVbo,
const boo::ObjToken<IGraphicsBuffer>& ibo,
size_t ubufCount, const boo::ObjToken<IGraphicsBuffer>* ubufs, const PipelineStage* ubufStages,
const size_t* ubufOffs, const size_t* ubufSizes,
size_t texCount, const boo::ObjToken<ITexture>* texs,
const int* bindIdxs, const bool* bindDepth,
size_t baseVert = 0, size_t baseInst = 0);
boo::ObjToken<IShaderDataBinding> newShaderDataBinding(
const boo::ObjToken<IShaderPipeline>& pipeline, const boo::ObjToken<IGraphicsBuffer>& vbo,
const boo::ObjToken<IGraphicsBuffer>& instVbo, const boo::ObjToken<IGraphicsBuffer>& ibo, size_t ubufCount,
const boo::ObjToken<IGraphicsBuffer>* ubufs, const PipelineStage* ubufStages, const size_t* ubufOffs,
const size_t* ubufSizes, size_t texCount, const boo::ObjToken<ITexture>* texs, const int* bindIdxs,
const bool* bindDepth, size_t baseVert = 0, size_t baseInst = 0);
};
static std::vector<uint8_t> CompileHLSL(const char* source, PipelineStage stage);
};
}
} // namespace boo
#endif // _WIN32

View File

@ -6,27 +6,24 @@
#include "boo/IGraphicsContext.hpp"
#include "GLSLMacros.hpp"
namespace boo
{
namespace boo {
struct BaseGraphicsData;
struct GLContext
{
struct GLContext {
uint32_t m_sampleCount = 1;
uint32_t m_anisotropy = 1;
bool m_deepColor = false;
};
class GLDataFactory : public IGraphicsDataFactory
{
class GLDataFactory : public IGraphicsDataFactory {
public:
class Context final : public IGraphicsDataFactory::Context
{
class Context final : public IGraphicsDataFactory::Context {
friend class GLDataFactoryImpl;
GLDataFactory& m_parent;
ObjToken<BaseGraphicsData> m_data;
Context(GLDataFactory& parent __BooTraceArgs);
~Context();
public:
Platform platform() const { return Platform::OpenGL; }
const SystemChar* platformName() const { return _SYS_STR("OpenGL"); }
@ -37,33 +34,28 @@ public:
ObjToken<ITextureS> newStaticTexture(size_t width, size_t height, size_t mips, TextureFormat fmt,
TextureClampMode clampMode, const void* data, size_t sz);
ObjToken<ITextureSA> newStaticArrayTexture(size_t width, size_t height, size_t layers, size_t mips,
TextureFormat fmt, TextureClampMode clampMode, const void* data, size_t sz);
TextureFormat fmt, TextureClampMode clampMode, const void* data,
size_t sz);
ObjToken<ITextureD> newDynamicTexture(size_t width, size_t height, TextureFormat fmt, TextureClampMode clampMode);
ObjToken<ITextureR> newRenderTexture(size_t width, size_t height, TextureClampMode clampMode,
size_t colorBindingCount, size_t depthBindingCount);
ObjToken<IShaderStage>
newShaderStage(const uint8_t* data, size_t size, PipelineStage stage);
ObjToken<IShaderStage> newShaderStage(const uint8_t* data, size_t size, PipelineStage stage);
ObjToken<IShaderPipeline>
newShaderPipeline(ObjToken<IShaderStage> vertex, ObjToken<IShaderStage> fragment,
ObjToken<IShaderPipeline> newShaderPipeline(ObjToken<IShaderStage> vertex, ObjToken<IShaderStage> fragment,
ObjToken<IShaderStage> geometry, ObjToken<IShaderStage> control,
ObjToken<IShaderStage> evaluation, const VertexFormatInfo& vtxFmt,
const AdditionalPipelineInfo& additionalInfo);
ObjToken<IShaderDataBinding>
newShaderDataBinding(const ObjToken<IShaderPipeline>& pipeline,
const ObjToken<IGraphicsBuffer>& vbo,
const ObjToken<IGraphicsBuffer>& instVbo,
const ObjToken<IGraphicsBuffer>& ibo,
size_t ubufCount, const ObjToken<IGraphicsBuffer>* ubufs, const PipelineStage* ubufStages,
const size_t* ubufOffs, const size_t* ubufSizes,
size_t texCount, const ObjToken<ITexture>* texs,
const int* texBindIdx, const bool* depthBind,
size_t baseVert = 0, size_t baseInst = 0);
ObjToken<IShaderDataBinding> newShaderDataBinding(
const ObjToken<IShaderPipeline>& pipeline, const ObjToken<IGraphicsBuffer>& vbo,
const ObjToken<IGraphicsBuffer>& instVbo, const ObjToken<IGraphicsBuffer>& ibo, size_t ubufCount,
const ObjToken<IGraphicsBuffer>* ubufs, const PipelineStage* ubufStages, const size_t* ubufOffs,
const size_t* ubufSizes, size_t texCount, const ObjToken<ITexture>* texs, const int* texBindIdx,
const bool* depthBind, size_t baseVert = 0, size_t baseInst = 0);
};
};
}
} // namespace boo
#endif

View File

@ -47,4 +47,3 @@
"#define TBINDING6\n" \
"#define TBINDING7\n" \
"#endif\n"

View File

@ -4,11 +4,9 @@
#include "boo/IWindow.hpp"
#include <functional>
namespace boo
{
namespace boo {
struct IGraphicsCommandQueue
{
struct IGraphicsCommandQueue {
virtual ~IGraphicsCommandQueue() = default;
using Platform = IGraphicsDataFactory::Platform;
@ -31,8 +29,8 @@ struct IGraphicsCommandQueue
virtual void drawInstances(size_t start, size_t count, size_t instCount, size_t startInst = 0) = 0;
virtual void drawInstancesIndexed(size_t start, size_t count, size_t instCount, size_t startInst = 0) = 0;
virtual void resolveBindTexture(const ObjToken<ITextureR>& texture, const SWindowRect& rect,
bool tlOrigin, int bindIdx, bool color, bool depth, bool clearDepth=false)=0;
virtual void resolveBindTexture(const ObjToken<ITextureR>& texture, const SWindowRect& rect, bool tlOrigin,
int bindIdx, bool color, bool depth, bool clearDepth = false) = 0;
virtual void resolveDisplay(const ObjToken<ITextureR>& source) = 0;
virtual void execute() = 0;
@ -40,5 +38,4 @@ struct IGraphicsCommandQueue
virtual void stopRenderer() = 0;
};
}
} // namespace boo

View File

@ -12,78 +12,48 @@
#include <ctype.h>
#endif
namespace boo
{
namespace boo {
struct IGraphicsCommandQueue;
/** Supported buffer uses */
enum class BufferUse
{
Null,
Vertex,
Index,
Uniform
};
enum class BufferUse { Null, Vertex, Index, Uniform };
/** Typeless graphics buffer */
struct IGraphicsBuffer : IObj
{
struct IGraphicsBuffer : IObj {
bool dynamic() const { return m_dynamic; }
protected:
bool m_dynamic;
explicit IGraphicsBuffer(bool dynamic) : m_dynamic(dynamic) {}
};
/** Static resource buffer for verts, indices, uniform constants */
struct IGraphicsBufferS : IGraphicsBuffer
{
struct IGraphicsBufferS : IGraphicsBuffer {
protected:
IGraphicsBufferS() : IGraphicsBuffer(false) {}
};
/** Dynamic resource buffer for verts, indices, uniform constants */
struct IGraphicsBufferD : IGraphicsBuffer
{
struct IGraphicsBufferD : IGraphicsBuffer {
virtual void load(const void* data, size_t sz) = 0;
virtual void* map(size_t sz) = 0;
virtual void unmap() = 0;
protected:
IGraphicsBufferD() : IGraphicsBuffer(true) {}
};
/** Texture access types */
enum class TextureType
{
Static,
StaticArray,
Dynamic,
Render
};
enum class TextureType { Static, StaticArray, Dynamic, Render };
/** Supported texture formats */
enum class TextureFormat
{
RGBA8,
I8,
I16,
DXT1,
PVRTC4
};
enum class TextureFormat { RGBA8, I8, I16, DXT1, PVRTC4 };
/** Supported texture clamp modes */
enum class TextureClampMode
{
Invalid = -1,
Repeat,
ClampToWhite,
ClampToBlack,
ClampToEdge,
ClampToEdgeNearest
};
enum class TextureClampMode { Invalid = -1, Repeat, ClampToWhite, ClampToBlack, ClampToEdge, ClampToEdgeNearest };
/** Typeless texture */
struct ITexture : IObj
{
struct ITexture : IObj {
TextureType type() const { return m_type; }
/* Only applies on GL and Vulkan. Use shader semantics on other platforms */
@ -95,39 +65,35 @@ protected:
};
/** Static resource buffer for textures */
struct ITextureS : ITexture
{
struct ITextureS : ITexture {
protected:
ITextureS() : ITexture(TextureType::Static) {}
};
/** Static-array resource buffer for array textures */
struct ITextureSA : ITexture
{
struct ITextureSA : ITexture {
protected:
ITextureSA() : ITexture(TextureType::StaticArray) {}
};
/** Dynamic resource buffer for textures */
struct ITextureD : ITexture
{
struct ITextureD : ITexture {
virtual void load(const void* data, size_t sz) = 0;
virtual void* map(size_t sz) = 0;
virtual void unmap() = 0;
protected:
ITextureD() : ITexture(TextureType::Dynamic) {}
};
/** Resource buffer for render-target textures */
struct ITextureR : ITexture
{
struct ITextureR : ITexture {
protected:
ITextureR() : ITexture(TextureType::Render) {}
};
/** Types of vertex attributes */
enum class VertexSemantic
{
enum class VertexSemantic {
None = 0,
Position3,
Position4,
@ -145,29 +111,24 @@ enum class VertexSemantic
ENABLE_BITWISE_ENUM(VertexSemantic)
/** Used to create IVertexFormat */
struct VertexElementDescriptor
{
struct VertexElementDescriptor {
VertexSemantic semantic;
int semanticIdx = 0;
VertexElementDescriptor() = default;
VertexElementDescriptor(VertexSemantic s, int idx=0)
: semantic(s), semanticIdx(idx) {}
VertexElementDescriptor(VertexSemantic s, int idx = 0) : semantic(s), semanticIdx(idx) {}
};
/** Structure for passing vertex format info for pipeline construction */
struct VertexFormatInfo
{
struct VertexFormatInfo {
size_t elementCount = 0;
const VertexElementDescriptor* elements = nullptr;
VertexFormatInfo() = default;
VertexFormatInfo(size_t sz, const VertexElementDescriptor* elem)
: elementCount(sz), elements(elem) {}
VertexFormatInfo(size_t sz, const VertexElementDescriptor* elem) : elementCount(sz), elements(elem) {}
template <typename T>
VertexFormatInfo(const T& tp)
: elementCount(std::extent_v<T>), elements(tp) {}
VertexFormatInfo(const T& tp) : elementCount(std::extent_v<T>), elements(tp) {}
VertexFormatInfo(const std::initializer_list<VertexElementDescriptor>& l)
: elementCount(l.size()), elements(l.begin()) {}
@ -186,35 +147,16 @@ struct IShaderPipeline : IObj {};
struct IShaderDataBinding : IObj {};
/** Used wherever distinction of pipeline stages is needed */
enum class PipelineStage
{
Null,
Vertex,
Fragment,
Geometry,
Control,
Evaluation
};
enum class PipelineStage { Null, Vertex, Fragment, Geometry, Control, Evaluation };
/** Used by platform shader pipeline constructors */
enum class Primitive
{
Triangles,
TriStrips,
Patches
};
enum class Primitive { Triangles, TriStrips, Patches };
/** Used by platform shader pipeline constructors */
enum class CullMode
{
None,
Backface,
Frontface
};
enum class CullMode { None, Backface, Frontface };
/** Used by platform shader pipeline constructors */
enum class ZTest
{
enum class ZTest {
None,
LEqual, /* Flipped on Vulkan, D3D, Metal */
Greater,
@ -223,8 +165,7 @@ enum class ZTest
};
/** Used by platform shader pipeline constructors */
enum class BlendFactor
{
enum class BlendFactor {
Zero,
One,
SrcColor,
@ -243,8 +184,7 @@ enum class BlendFactor
};
/** Structure for passing additional pipeline construction information */
struct AdditionalPipelineInfo
{
struct AdditionalPipelineInfo {
BlendFactor srcFac = BlendFactor::One;
BlendFactor dstFac = BlendFactor::Zero;
Primitive prim = Primitive::TriStrips;
@ -259,92 +199,66 @@ struct AdditionalPipelineInfo
};
/** Factory object for creating batches of resources as an IGraphicsData token */
struct IGraphicsDataFactory
{
struct IGraphicsDataFactory {
virtual ~IGraphicsDataFactory() = default;
enum class Platform
{
Null,
OpenGL,
D3D11,
Metal,
Vulkan,
GX,
NX
};
enum class Platform { Null, OpenGL, D3D11, Metal, Vulkan, GX, NX };
virtual Platform platform() const = 0;
virtual const SystemChar* platformName() const = 0;
struct Context
{
struct Context {
virtual Platform platform() const = 0;
virtual const SystemChar* platformName() const = 0;
virtual ObjToken<IGraphicsBufferS>
newStaticBuffer(BufferUse use, const void* data, size_t stride, size_t count)=0;
virtual ObjToken<IGraphicsBufferD>
newDynamicBuffer(BufferUse use, size_t stride, size_t count)=0;
virtual ObjToken<IGraphicsBufferS> newStaticBuffer(BufferUse use, const void* data, size_t stride,
size_t count) = 0;
virtual ObjToken<IGraphicsBufferD> newDynamicBuffer(BufferUse use, size_t stride, size_t count) = 0;
virtual ObjToken<ITextureS>
newStaticTexture(size_t width, size_t height, size_t mips, TextureFormat fmt,
virtual ObjToken<ITextureS> newStaticTexture(size_t width, size_t height, size_t mips, TextureFormat fmt,
TextureClampMode clampMode, const void* data, size_t sz) = 0;
virtual ObjToken<ITextureSA>
newStaticArrayTexture(size_t width, size_t height, size_t layers, size_t mips,
TextureFormat fmt, TextureClampMode clampMode, const void* data, size_t sz)=0;
virtual ObjToken<ITextureD>
newDynamicTexture(size_t width, size_t height, TextureFormat fmt, TextureClampMode clampMode)=0;
virtual ObjToken<ITextureR>
newRenderTexture(size_t width, size_t height, TextureClampMode clampMode,
virtual ObjToken<ITextureSA> newStaticArrayTexture(size_t width, size_t height, size_t layers, size_t mips,
TextureFormat fmt, TextureClampMode clampMode, const void* data,
size_t sz) = 0;
virtual ObjToken<ITextureD> newDynamicTexture(size_t width, size_t height, TextureFormat fmt,
TextureClampMode clampMode) = 0;
virtual ObjToken<ITextureR> newRenderTexture(size_t width, size_t height, TextureClampMode clampMode,
size_t colorBindingCount, size_t depthBindingCount) = 0;
virtual ObjToken<IShaderStage>
newShaderStage(const uint8_t* data, size_t size, PipelineStage stage)=0;
virtual ObjToken<IShaderStage> newShaderStage(const uint8_t* data, size_t size, PipelineStage stage) = 0;
ObjToken<IShaderStage>
newShaderStage(const std::vector<uint8_t>& data, PipelineStage stage)
{
ObjToken<IShaderStage> newShaderStage(const std::vector<uint8_t>& data, PipelineStage stage) {
return newShaderStage(data.data(), data.size(), stage);
}
virtual ObjToken<IShaderPipeline>
newShaderPipeline(ObjToken<IShaderStage> vertex, ObjToken<IShaderStage> fragment,
virtual ObjToken<IShaderPipeline> newShaderPipeline(ObjToken<IShaderStage> vertex, ObjToken<IShaderStage> fragment,
ObjToken<IShaderStage> geometry, ObjToken<IShaderStage> control,
ObjToken<IShaderStage> evaluation, const VertexFormatInfo& vtxFmt,
ObjToken<IShaderStage> evaluation,
const VertexFormatInfo& vtxFmt,
const AdditionalPipelineInfo& additionalInfo) = 0;
ObjToken<IShaderPipeline>
newShaderPipeline(ObjToken<IShaderStage> vertex, ObjToken<IShaderStage> fragment,
const VertexFormatInfo& vtxFmt, const AdditionalPipelineInfo& additionalInfo)
{
ObjToken<IShaderPipeline> newShaderPipeline(ObjToken<IShaderStage> vertex, ObjToken<IShaderStage> fragment,
const VertexFormatInfo& vtxFmt,
const AdditionalPipelineInfo& additionalInfo) {
return newShaderPipeline(vertex, fragment, {}, {}, {}, vtxFmt, additionalInfo);
}
virtual ObjToken<IShaderDataBinding>
newShaderDataBinding(const ObjToken<IShaderPipeline>& pipeline,
const ObjToken<IGraphicsBuffer>& vbo,
const ObjToken<IGraphicsBuffer>& instVbo,
const ObjToken<IGraphicsBuffer>& ibo,
size_t ubufCount, const ObjToken<IGraphicsBuffer>* ubufs, const PipelineStage* ubufStages,
const size_t* ubufOffs, const size_t* ubufSizes,
size_t texCount, const ObjToken<ITexture>* texs,
const int* texBindIdx, const bool* depthBind,
size_t baseVert = 0, size_t baseInst = 0)=0;
virtual ObjToken<IShaderDataBinding> newShaderDataBinding(
const ObjToken<IShaderPipeline>& pipeline, const ObjToken<IGraphicsBuffer>& vbo,
const ObjToken<IGraphicsBuffer>& instVbo, const ObjToken<IGraphicsBuffer>& ibo, size_t ubufCount,
const ObjToken<IGraphicsBuffer>* ubufs, const PipelineStage* ubufStages, const size_t* ubufOffs,
const size_t* ubufSizes, size_t texCount, const ObjToken<ITexture>* texs, const int* texBindIdx,
const bool* depthBind, size_t baseVert = 0, size_t baseInst = 0) = 0;
ObjToken<IShaderDataBinding>
newShaderDataBinding(const ObjToken<IShaderPipeline>& pipeline,
ObjToken<IShaderDataBinding> newShaderDataBinding(const ObjToken<IShaderPipeline>& pipeline,
const ObjToken<IGraphicsBuffer>& vbo,
const ObjToken<IGraphicsBuffer>& instVbo,
const ObjToken<IGraphicsBuffer>& ibo,
size_t ubufCount, const ObjToken<IGraphicsBuffer>* ubufs, const PipelineStage* ubufStages,
size_t texCount, const ObjToken<ITexture>* texs,
const int* texBindIdx, const bool* depthBind,
size_t baseVert = 0, size_t baseInst = 0)
{
return newShaderDataBinding(pipeline, vbo, instVbo, ibo,
ubufCount, ubufs, ubufStages, nullptr,
nullptr, texCount, texs, texBindIdx, depthBind,
baseVert, baseInst);
const ObjToken<IGraphicsBuffer>& ibo, size_t ubufCount,
const ObjToken<IGraphicsBuffer>* ubufs,
const PipelineStage* ubufStages, size_t texCount,
const ObjToken<ITexture>* texs, const int* texBindIdx,
const bool* depthBind, size_t baseVert = 0, size_t baseInst = 0) {
return newShaderDataBinding(pipeline, vbo, instVbo, ibo, ubufCount, ubufs, ubufStages, nullptr, nullptr, texCount,
texs, texBindIdx, depthBind, baseVert, baseInst);
}
};
@ -357,5 +271,4 @@ struct IGraphicsDataFactory
using GraphicsDataFactoryContext = IGraphicsDataFactory::Context;
using FactoryCommitFunc = std::function<bool(GraphicsDataFactoryContext& ctx)>;
}
} // namespace boo

View File

@ -6,20 +6,18 @@
#include "IGraphicsCommandQueue.hpp"
#include "boo/IGraphicsContext.hpp"
namespace boo
{
namespace boo {
struct BaseGraphicsData;
class MetalDataFactory : public IGraphicsDataFactory
{
class MetalDataFactory : public IGraphicsDataFactory {
public:
class Context final : public IGraphicsDataFactory::Context
{
class Context final : public IGraphicsDataFactory::Context {
friend class MetalDataFactoryImpl;
MetalDataFactory& m_parent;
ObjToken<BaseGraphicsData> m_data;
Context(MetalDataFactory& parent __BooTraceArgs);
~Context();
public:
Platform platform() const { return Platform::Metal; }
const SystemChar* platformName() const { return _SYS_STR("Metal"); }
@ -32,10 +30,9 @@ public:
ObjToken<ITextureSA> newStaticArrayTexture(size_t width, size_t height, size_t layers, size_t mips,
TextureFormat fmt, TextureClampMode clampMode, const void* data,
size_t sz);
ObjToken<ITextureD> newDynamicTexture(size_t width, size_t height, TextureFormat fmt,
TextureClampMode clampMode);
ObjToken<ITextureR> newRenderTexture(size_t width, size_t height, TextureClampMode clampMode,
size_t colorBindCount, size_t depthBindCount);
ObjToken<ITextureD> newDynamicTexture(size_t width, size_t height, TextureFormat fmt, TextureClampMode clampMode);
ObjToken<ITextureR> newRenderTexture(size_t width, size_t height, TextureClampMode clampMode, size_t colorBindCount,
size_t depthBindCount);
ObjToken<IShaderStage> newShaderStage(const uint8_t* data, size_t size, PipelineStage stage);
@ -44,22 +41,18 @@ public:
ObjToken<IShaderStage> evaluation, const VertexFormatInfo& vtxFmt,
const AdditionalPipelineInfo& additionalInfo);
ObjToken<IShaderDataBinding>
newShaderDataBinding(const ObjToken<IShaderPipeline>& pipeline,
const ObjToken<IGraphicsBuffer>& vbo,
const ObjToken<IGraphicsBuffer>& instVbo,
const ObjToken<IGraphicsBuffer>& ibo,
size_t ubufCount, const ObjToken<IGraphicsBuffer>* ubufs, const PipelineStage* ubufStages,
const size_t* ubufOffs, const size_t* ubufSizes,
size_t texCount, const ObjToken<ITexture>* texs,
const int* texBindIdxs, const bool* depthBind,
size_t baseVert = 0, size_t baseInst = 0);
ObjToken<IShaderDataBinding> newShaderDataBinding(
const ObjToken<IShaderPipeline>& pipeline, const ObjToken<IGraphicsBuffer>& vbo,
const ObjToken<IGraphicsBuffer>& instVbo, const ObjToken<IGraphicsBuffer>& ibo, size_t ubufCount,
const ObjToken<IGraphicsBuffer>* ubufs, const PipelineStage* ubufStages, const size_t* ubufOffs,
const size_t* ubufSizes, size_t texCount, const ObjToken<ITexture>* texs, const int* texBindIdxs,
const bool* depthBind, size_t baseVert = 0, size_t baseInst = 0);
};
static std::vector<uint8_t> CompileMetal(const char* source, PipelineStage stage);
};
}
} // namespace boo
#endif
#endif // __APPLE__

View File

@ -12,12 +12,10 @@ struct pipe_context;
struct st_context;
struct pipe_surface;
namespace boo
{
namespace boo {
struct BaseGraphicsData;
struct NXContext
{
struct NXContext {
struct pipe_surface* m_windowSurfaces[2];
NvFence m_fences[2];
bool m_fence_swap;
@ -40,16 +38,15 @@ struct NXContext
std::unordered_map<uint64_t, void*> m_vtxElemStates;
};
class NXDataFactory : public IGraphicsDataFactory
{
class NXDataFactory : public IGraphicsDataFactory {
public:
class Context final : public IGraphicsDataFactory::Context
{
class Context final : public IGraphicsDataFactory::Context {
friend class NXDataFactoryImpl;
NXDataFactory& m_parent;
boo::ObjToken<BaseGraphicsData> m_data;
Context(NXDataFactory& parent __BooTraceArgs);
~Context();
public:
Platform platform() const { return Platform::NX; }
const SystemChar* platformName() const { return _SYS_STR("NX"); }
@ -60,34 +57,29 @@ public:
boo::ObjToken<ITextureS> newStaticTexture(size_t width, size_t height, size_t mips, TextureFormat fmt,
TextureClampMode clampMode, const void* data, size_t sz);
boo::ObjToken<ITextureSA> newStaticArrayTexture(size_t width, size_t height, size_t layers, size_t mips,
TextureFormat fmt, TextureClampMode clampMode,
const void* data, size_t sz);
boo::ObjToken<ITextureD> newDynamicTexture(size_t width, size_t height, TextureFormat fmt, TextureClampMode clampMode);
TextureFormat fmt, TextureClampMode clampMode, const void* data,
size_t sz);
boo::ObjToken<ITextureD> newDynamicTexture(size_t width, size_t height, TextureFormat fmt,
TextureClampMode clampMode);
boo::ObjToken<ITextureR> newRenderTexture(size_t width, size_t height, TextureClampMode clampMode,
size_t colorBindCount, size_t depthBindCount);
ObjToken<IShaderStage>
newShaderStage(const uint8_t* data, size_t size, PipelineStage stage);
ObjToken<IShaderStage> newShaderStage(const uint8_t* data, size_t size, PipelineStage stage);
ObjToken<IShaderPipeline>
newShaderPipeline(ObjToken<IShaderStage> vertex, ObjToken<IShaderStage> fragment,
ObjToken<IShaderPipeline> newShaderPipeline(ObjToken<IShaderStage> vertex, ObjToken<IShaderStage> fragment,
ObjToken<IShaderStage> geometry, ObjToken<IShaderStage> control,
ObjToken<IShaderStage> evaluation, const VertexFormatInfo& vtxFmt,
const AdditionalPipelineInfo& additionalInfo);
boo::ObjToken<IShaderDataBinding>
newShaderDataBinding(const boo::ObjToken<IShaderPipeline>& pipeline,
const boo::ObjToken<IGraphicsBuffer>& vbo,
const boo::ObjToken<IGraphicsBuffer>& instVbo,
const boo::ObjToken<IGraphicsBuffer>& ibo,
size_t ubufCount, const boo::ObjToken<IGraphicsBuffer>* ubufs, const PipelineStage* ubufStages,
const size_t* ubufOffs, const size_t* ubufSizes,
size_t texCount, const boo::ObjToken<ITexture>* texs,
const int* bindIdxs, const bool* bindDepth,
size_t baseVert = 0, size_t baseInst = 0);
boo::ObjToken<IShaderDataBinding> newShaderDataBinding(
const boo::ObjToken<IShaderPipeline>& pipeline, const boo::ObjToken<IGraphicsBuffer>& vbo,
const boo::ObjToken<IGraphicsBuffer>& instVbo, const boo::ObjToken<IGraphicsBuffer>& ibo, size_t ubufCount,
const boo::ObjToken<IGraphicsBuffer>* ubufs, const PipelineStage* ubufStages, const size_t* ubufOffs,
const size_t* ubufSizes, size_t texCount, const boo::ObjToken<ITexture>* texs, const int* bindIdxs,
const bool* bindDepth, size_t baseVert = 0, size_t baseInst = 0);
};
};
}
} // namespace boo
#endif

View File

@ -15,14 +15,11 @@
/* Forward-declare handle type for Vulkan Memory Allocator */
struct VmaAllocator_T;
namespace boo
{
namespace boo {
struct BaseGraphicsData;
struct VulkanContext
{
struct LayerProperties
{
struct VulkanContext {
struct LayerProperties {
VkLayerProperties properties;
std::vector<VkExtensionProperties> extensions;
};
@ -52,14 +49,11 @@ struct VulkanContext
VkFormat m_displayFormat;
VkFormat m_internalFormat;
struct Window
{
struct SwapChain
{
struct Window {
struct SwapChain {
VkFormat m_format = VK_FORMAT_UNDEFINED;
VkSwapchainKHR m_swapChain = VK_NULL_HANDLE;
struct Buffer
{
struct Buffer {
VkImage m_image = VK_NULL_HANDLE;
VkImageView m_colorView = VK_NULL_HANDLE;
VkFramebuffer m_framebuffer = VK_NULL_HANDLE;
@ -69,13 +63,11 @@ struct VulkanContext
};
std::vector<Buffer> m_bufs;
uint32_t m_backBuf = 0;
void destroy(VkDevice dev)
{
void destroy(VkDevice dev) {
for (Buffer& buf : m_bufs)
buf.destroy(dev);
m_bufs.clear();
if (m_swapChain)
{
if (m_swapChain) {
vk::DestroySwapchainKHR(dev, m_swapChain, nullptr);
m_swapChain = VK_NULL_HANDLE;
}
@ -108,38 +100,33 @@ struct VulkanContext
void destroyDevice();
void initSwapChain(Window& windowCtx, VkSurfaceKHR surface, VkFormat format, VkColorSpaceKHR colorspace);
struct SwapChainResize
{
struct SwapChainResize {
Window& m_windowCtx;
VkSurfaceKHR m_surface;
VkFormat m_format;
VkColorSpaceKHR m_colorspace;
SWindowRect m_rect;
SwapChainResize(Window& windowCtx, VkSurfaceKHR surface,
VkFormat format, VkColorSpaceKHR colorspace,
SwapChainResize(Window& windowCtx, VkSurfaceKHR surface, VkFormat format, VkColorSpaceKHR colorspace,
const SWindowRect& rect)
: m_windowCtx(windowCtx), m_surface(surface),
m_format(format), m_colorspace(colorspace), m_rect(rect) {}
: m_windowCtx(windowCtx), m_surface(surface), m_format(format), m_colorspace(colorspace), m_rect(rect) {}
};
std::queue<SwapChainResize> m_deferredResizes;
std::mutex m_resizeLock;
void resizeSwapChain(Window& windowCtx, VkSurfaceKHR surface,
VkFormat format, VkColorSpaceKHR colorspace,
void resizeSwapChain(Window& windowCtx, VkSurfaceKHR surface, VkFormat format, VkColorSpaceKHR colorspace,
const SWindowRect& rect);
bool _resizeSwapChains();
};
extern VulkanContext g_VulkanContext;
class VulkanDataFactory : public IGraphicsDataFactory
{
class VulkanDataFactory : public IGraphicsDataFactory {
public:
class Context final : public IGraphicsDataFactory::Context
{
class Context final : public IGraphicsDataFactory::Context {
friend class VulkanDataFactoryImpl;
VulkanDataFactory& m_parent;
boo::ObjToken<BaseGraphicsData> m_data;
Context(VulkanDataFactory& parent __BooTraceArgs);
~Context();
public:
Platform platform() const { return Platform::Vulkan; }
const SystemChar* platformName() const { return _SYS_STR("Vulkan"); }
@ -150,36 +137,31 @@ public:
boo::ObjToken<ITextureS> newStaticTexture(size_t width, size_t height, size_t mips, TextureFormat fmt,
TextureClampMode clampMode, const void* data, size_t sz);
boo::ObjToken<ITextureSA> newStaticArrayTexture(size_t width, size_t height, size_t layers, size_t mips,
TextureFormat fmt, TextureClampMode clampMode,
const void* data, size_t sz);
boo::ObjToken<ITextureD> newDynamicTexture(size_t width, size_t height, TextureFormat fmt, TextureClampMode clampMode);
TextureFormat fmt, TextureClampMode clampMode, const void* data,
size_t sz);
boo::ObjToken<ITextureD> newDynamicTexture(size_t width, size_t height, TextureFormat fmt,
TextureClampMode clampMode);
boo::ObjToken<ITextureR> newRenderTexture(size_t width, size_t height, TextureClampMode clampMode,
size_t colorBindCount, size_t depthBindCount);
ObjToken<IShaderStage>
newShaderStage(const uint8_t* data, size_t size, PipelineStage stage);
ObjToken<IShaderStage> newShaderStage(const uint8_t* data, size_t size, PipelineStage stage);
ObjToken<IShaderPipeline>
newShaderPipeline(ObjToken<IShaderStage> vertex, ObjToken<IShaderStage> fragment,
ObjToken<IShaderPipeline> newShaderPipeline(ObjToken<IShaderStage> vertex, ObjToken<IShaderStage> fragment,
ObjToken<IShaderStage> geometry, ObjToken<IShaderStage> control,
ObjToken<IShaderStage> evaluation, const VertexFormatInfo& vtxFmt,
const AdditionalPipelineInfo& additionalInfo);
boo::ObjToken<IShaderDataBinding>
newShaderDataBinding(const boo::ObjToken<IShaderPipeline>& pipeline,
const boo::ObjToken<IGraphicsBuffer>& vbo,
const boo::ObjToken<IGraphicsBuffer>& instVbo,
const boo::ObjToken<IGraphicsBuffer>& ibo,
size_t ubufCount, const boo::ObjToken<IGraphicsBuffer>* ubufs, const PipelineStage* ubufStages,
const size_t* ubufOffs, const size_t* ubufSizes,
size_t texCount, const boo::ObjToken<ITexture>* texs,
const int* bindIdxs, const bool* bindDepth,
size_t baseVert = 0, size_t baseInst = 0);
boo::ObjToken<IShaderDataBinding> newShaderDataBinding(
const boo::ObjToken<IShaderPipeline>& pipeline, const boo::ObjToken<IGraphicsBuffer>& vbo,
const boo::ObjToken<IGraphicsBuffer>& instVbo, const boo::ObjToken<IGraphicsBuffer>& ibo, size_t ubufCount,
const boo::ObjToken<IGraphicsBuffer>* ubufs, const PipelineStage* ubufStages, const size_t* ubufOffs,
const size_t* ubufSizes, size_t texCount, const boo::ObjToken<ITexture>* texs, const int* bindIdxs,
const bool* bindDepth, size_t baseVert = 0, size_t baseInst = 0);
};
static std::vector<uint8_t> CompileGLSL(const char* source, PipelineStage stage);
};
}
} // namespace boo
#endif

View File

@ -214,4 +214,3 @@ void init_dispatch_table_middle(VkInstance instance, bool include_bottom);
void init_dispatch_table_bottom(VkInstance instance, VkDevice dev);
} // namespace vk

View File

@ -3,8 +3,7 @@
#include <string>
/* These match mesa's internal stages */
enum class nx_shader_stage
{
enum class nx_shader_stage {
NONE = -1,
VERTEX = 0,
TESS_CTRL = 1,
@ -14,8 +13,7 @@ enum class nx_shader_stage
COMPUTE = 5,
};
struct standalone_options
{
struct standalone_options {
int glsl_version;
int dump_ast;
int dump_hir;
@ -26,12 +24,12 @@ struct standalone_options
};
class nx_compiler;
class nx_shader_stage_object
{
class nx_shader_stage_object {
friend class nx_compiler;
nx_compiler* m_parent = nullptr;
struct gl_shader* m_shader = nullptr;
nx_shader_stage_object(nx_compiler& parent) : m_parent(&parent) {}
public:
nx_shader_stage_object() = default;
nx_shader_stage_object(const nx_shader_stage_object&);
@ -43,12 +41,12 @@ public:
const char* info_log() const;
};
class nx_linked_shader
{
class nx_linked_shader {
friend class nx_compiler;
nx_compiler* m_parent = nullptr;
struct gl_shader_program* m_program = nullptr;
nx_linked_shader(nx_compiler& parent) : m_parent(&parent) {}
public:
nx_linked_shader() = default;
nx_linked_shader(const nx_linked_shader&);
@ -59,8 +57,7 @@ public:
const struct gl_shader_program* program() const { return m_program; }
};
class nx_compiler
{
class nx_compiler {
friend class nx_shader_stage_object;
friend class nx_linked_shader;
struct pipe_screen* m_screen = nullptr;
@ -68,14 +65,14 @@ class nx_compiler
struct standalone_options m_options = {};
bool m_ownsCtx = false;
void compile_shader(struct gl_context* ctx, struct gl_shader* shader);
public:
nx_compiler();
~nx_compiler();
bool initialize(struct pipe_screen *screen, struct st_context *st,
const struct standalone_options *o = nullptr);
bool initialize(struct pipe_screen* screen, struct st_context* st, const struct standalone_options* o = nullptr);
bool initialize(const struct standalone_options* o = nullptr);
nx_shader_stage_object compile(nx_shader_stage type, const char* source);
nx_linked_shader link(unsigned num_stages, const nx_shader_stage_object** stages, std::string* infoLog = nullptr);
std::pair<std::shared_ptr<uint8_t[]>, size_t>
offline_link(unsigned num_stages, const nx_shader_stage_object **stages, std::string* infoLog = nullptr);
std::pair<std::shared_ptr<uint8_t[]>, size_t> offline_link(unsigned num_stages, const nx_shader_stage_object** stages,
std::string* infoLog = nullptr);
};

View File

@ -1,7 +1,3 @@
#pragma once
namespace boo
{
}
namespace boo {}

View File

@ -13,20 +13,13 @@
#include <hidsdi.h>
#endif
namespace boo
{
namespace boo {
class DeviceToken;
class IHIDDevice;
enum class HIDReportType
{
Input,
Output,
Feature
};
enum class HIDReportType { Input, Output, Feature };
class DeviceBase : public std::enable_shared_from_this<DeviceBase>
{
class DeviceBase : public std::enable_shared_from_this<DeviceBase> {
friend class DeviceToken;
friend struct DeviceSignature;
friend class HIDDeviceIOKit;
@ -69,24 +62,24 @@ public:
std::vector<uint8_t> getReportDescriptor();
#endif
bool sendHIDReport(const uint8_t* data, size_t length, HIDReportType tp, uint32_t message = 0);
size_t receiveHIDReport(uint8_t* data, size_t length, HIDReportType tp, uint32_t message=0); // Prefer callback version
virtual void receivedHIDReport(const uint8_t* /*data*/, size_t /*length*/, HIDReportType /*tp*/, uint32_t /*message*/) {}
size_t receiveHIDReport(uint8_t* data, size_t length, HIDReportType tp,
uint32_t message = 0); // Prefer callback version
virtual void receivedHIDReport(const uint8_t* /*data*/, size_t /*length*/, HIDReportType /*tp*/,
uint32_t /*message*/) {}
};
template <class CB>
class TDeviceBase : public DeviceBase
{
class TDeviceBase : public DeviceBase {
protected:
std::mutex m_callbackLock;
CB* m_callback = nullptr;
public:
TDeviceBase(uint64_t typeHash, DeviceToken* token) : DeviceBase(typeHash, token) {}
void setCallback(CB* cb)
{
void setCallback(CB* cb) {
std::lock_guard<std::mutex> lk(m_callbackLock);
m_callback = cb;
}
};
}
} // namespace boo

View File

@ -16,11 +16,9 @@
#include <windows.h>
#endif
namespace boo
{
namespace boo {
class DeviceFinder
{
class DeviceFinder {
public:
friend class HIDListenerIOKit;
friend class HIDListenerUdev;
@ -43,31 +41,25 @@ private:
/* Friend methods for platform-listener to find/insert/remove
* tokens with type-filtering */
inline bool _hasToken(const std::string& path)
{
inline bool _hasToken(const std::string& path) {
auto preCheck = m_tokens.find(path);
if (preCheck != m_tokens.end())
return true;
return false;
}
inline bool _insertToken(std::unique_ptr<DeviceToken>&& token)
{
if (DeviceSignature::DeviceMatchToken(*token, m_types))
{
inline bool _insertToken(std::unique_ptr<DeviceToken>&& token) {
if (DeviceSignature::DeviceMatchToken(*token, m_types)) {
m_tokensLock.lock();
TInsertedDeviceToken inseredTok =
m_tokens.insert(std::make_pair(token->getDevicePath(), std::move(token)));
TInsertedDeviceToken inseredTok = m_tokens.insert(std::make_pair(token->getDevicePath(), std::move(token)));
m_tokensLock.unlock();
deviceConnected(*inseredTok.first->second);
return true;
}
return false;
}
inline void _removeToken(const std::string& path)
{
inline void _removeToken(const std::string& path) {
auto preCheck = m_tokens.find(path);
if (preCheck != m_tokens.end())
{
if (preCheck != m_tokens.end()) {
DeviceToken& tok = *preCheck->second;
std::shared_ptr<DeviceBase> dev = tok.m_connectedDev;
tok._deviceClose();
@ -79,40 +71,33 @@ private:
}
public:
class CDeviceTokensHandle
{
class CDeviceTokensHandle {
DeviceFinder& m_finder;
public:
inline CDeviceTokensHandle(DeviceFinder& finder) : m_finder(finder)
{m_finder.m_tokensLock.lock();}
inline CDeviceTokensHandle(DeviceFinder& finder) : m_finder(finder) { m_finder.m_tokensLock.lock(); }
inline ~CDeviceTokensHandle() { m_finder.m_tokensLock.unlock(); }
inline TDeviceTokens::iterator begin() { return m_finder.m_tokens.begin(); }
inline TDeviceTokens::iterator end() { return m_finder.m_tokens.end(); }
};
/* Application must specify its interested device-types */
DeviceFinder(std::unordered_set<uint64_t> types)
{
if (skDevFinder)
{
DeviceFinder(std::unordered_set<uint64_t> types) {
if (skDevFinder) {
fprintf(stderr, "only one instance of CDeviceFinder may be constructed");
abort();
}
skDevFinder = this;
for (const uint64_t& typeHash : types)
{
for (const uint64_t& typeHash : types) {
const DeviceSignature* sigIter = BOO_DEVICE_SIGS;
while (sigIter->m_name)
{
while (sigIter->m_name) {
if (sigIter->m_typeHash == typeHash)
m_types.push_back(sigIter);
++sigIter;
}
}
}
virtual ~DeviceFinder()
{
virtual ~DeviceFinder() {
if (m_listener)
m_listener->stopScanning();
skDevFinder = NULL;
@ -125,16 +110,14 @@ public:
inline CDeviceTokensHandle getTokens() { return CDeviceTokensHandle(*this); }
/* Automatic device scanning */
inline bool startScanning()
{
inline bool startScanning() {
if (!m_listener)
m_listener = IHIDListenerNew(*this);
if (m_listener)
return m_listener->startScanning();
return false;
}
inline bool stopScanning()
{
inline bool stopScanning() {
if (!m_listener)
m_listener = IHIDListenerNew(*this);
if (m_listener)
@ -143,8 +126,7 @@ public:
}
/* Manual device scanning */
inline bool scanNow()
{
inline bool scanNow() {
if (!m_listener)
m_listener = IHIDListenerNew(*this);
if (m_listener)
@ -159,8 +141,6 @@ public:
/* Windows-specific WM_DEVICECHANGED handler */
static LRESULT winDevChangedHandler(WPARAM wParam, LPARAM lParam);
#endif
};
}
} // namespace boo

View File

@ -6,25 +6,16 @@
#include <memory>
#include <string>
namespace boo
{
namespace boo {
enum class DeviceType
{
None = 0,
USB = 1,
Bluetooth = 2,
HID = 3,
XInput = 4
};
enum class DeviceType { None = 0, USB = 1, Bluetooth = 2, HID = 3, XInput = 4 };
class DeviceToken;
class DeviceBase;
#define dev_typeid(type) std::hash<std::string>()(#type)
struct DeviceSignature
{
struct DeviceSignature {
typedef std::vector<const DeviceSignature*> TDeviceSignatureSet;
typedef std::function<std::shared_ptr<DeviceBase>(DeviceToken*)> TFactoryLambda;
const char* m_name;
@ -33,10 +24,9 @@ struct DeviceSignature
TFactoryLambda m_factory;
DeviceType m_type;
DeviceSignature() : m_name(NULL), m_typeHash(dev_typeid(DeviceSignature)) {} /* Sentinel constructor */
DeviceSignature(const char* name, uint64_t typeHash, unsigned vid, unsigned pid,
TFactoryLambda&& factory, DeviceType type=DeviceType::None)
: m_name(name), m_typeHash(typeHash), m_vid(vid), m_pid(pid),
m_factory(factory), m_type(type) {}
DeviceSignature(const char* name, uint64_t typeHash, unsigned vid, unsigned pid, TFactoryLambda&& factory,
DeviceType type = DeviceType::None)
: m_name(name), m_typeHash(typeHash), m_vid(vid), m_pid(pid), m_factory(factory), m_type(type) {}
static bool DeviceMatchToken(const DeviceToken& token, const TDeviceSignatureSet& sigSet);
static std::shared_ptr<DeviceBase> DeviceNew(DeviceToken& token);
};
@ -48,6 +38,4 @@ struct DeviceSignature
extern const DeviceSignature BOO_DEVICE_SIGS[];
}
} // namespace boo

View File

@ -4,11 +4,9 @@
#include "DeviceBase.hpp"
#include "DeviceSignature.hpp"
namespace boo
{
namespace boo {
class DeviceToken
{
class DeviceToken {
friend struct DeviceSignature;
friend class HIDListenerWinUSB;
DeviceType m_devType;
@ -22,32 +20,25 @@ class DeviceToken
std::shared_ptr<DeviceBase> m_connectedDev;
friend class DeviceFinder;
inline void _deviceClose()
{
inline void _deviceClose() {
if (m_connectedDev)
m_connectedDev->_deviceDisconnected();
m_connectedDev = NULL;
}
public:
DeviceToken(const DeviceToken&) = delete;
DeviceToken(const DeviceToken&& other)
: m_devType(other.m_devType),
m_vendorId(other.m_vendorId),
m_productId(other.m_productId),
m_vendorName(other.m_vendorName),
m_productName(other.m_productName),
m_devPath(other.m_devPath),
m_connectedDev(other.m_connectedDev)
{}
inline DeviceToken(DeviceType devType, unsigned vid, unsigned pid, const char* vname, const char* pname, const char* path)
: m_devType(devType),
m_vendorId(vid),
m_productId(pid),
m_devPath(path),
m_connectedDev(NULL)
{
: m_devType(other.m_devType)
, m_vendorId(other.m_vendorId)
, m_productId(other.m_productId)
, m_vendorName(other.m_vendorName)
, m_productName(other.m_productName)
, m_devPath(other.m_devPath)
, m_connectedDev(other.m_connectedDev) {}
inline DeviceToken(DeviceType devType, unsigned vid, unsigned pid, const char* vname, const char* pname,
const char* path)
: m_devType(devType), m_vendorId(vid), m_productId(pid), m_devPath(path), m_connectedDev(NULL) {
if (vname)
m_vendorName = vname;
if (pname)
@ -61,18 +52,14 @@ public:
inline std::string_view getProductName() const { return m_productName; }
inline std::string_view getDevicePath() const { return m_devPath; }
inline bool isDeviceOpen() const { return (m_connectedDev != NULL); }
inline std::shared_ptr<DeviceBase> openAndGetDevice()
{
inline std::shared_ptr<DeviceBase> openAndGetDevice() {
if (!m_connectedDev)
m_connectedDev = DeviceSignature::DeviceNew(*this);
return m_connectedDev;
}
inline bool operator ==(const DeviceToken& rhs) const
{return m_devPath == rhs.m_devPath;}
inline bool operator <(const DeviceToken& rhs) const
{return m_devPath < rhs.m_devPath;}
inline bool operator==(const DeviceToken& rhs) const { return m_devPath == rhs.m_devPath; }
inline bool operator<(const DeviceToken& rhs) const { return m_devPath < rhs.m_devPath; }
};
}
} // namespace boo

View File

@ -4,19 +4,16 @@
#include "DeviceBase.hpp"
#include "../System.hpp"
namespace boo
{
namespace boo {
enum class EDolphinControllerType
{
enum class EDolphinControllerType {
None = 0,
Normal = 0x10,
Wavebird = 0x20,
};
ENABLE_BITWISE_ENUM(EDolphinControllerType)
enum class EDolphinControllerButtons
{
enum class EDolphinControllerButtons {
Start = 1 << 0,
Z = 1 << 1,
R = 1 << 2,
@ -32,14 +29,12 @@ enum class EDolphinControllerButtons
};
ENABLE_BITWISE_ENUM(EDolphinControllerButtons)
struct DolphinControllerState
{
struct DolphinControllerState {
int16_t m_leftStick[2] = {0};
int16_t m_rightStick[2] = {0};
int16_t m_analogTriggers[2] = {0};
uint16_t m_btns = 0;
void reset()
{
void reset() {
m_leftStick[0] = 0;
m_leftStick[1] = 0;
m_rightStick[0] = 0;
@ -51,16 +46,20 @@ struct DolphinControllerState
void clamp();
};
struct IDolphinSmashAdapterCallback
{
virtual void controllerConnected(unsigned idx, EDolphinControllerType type) {(void)idx;(void)type;}
struct IDolphinSmashAdapterCallback {
virtual void controllerConnected(unsigned idx, EDolphinControllerType type) {
(void)idx;
(void)type;
}
virtual void controllerDisconnected(unsigned idx) { (void)idx; }
virtual void controllerUpdate(unsigned idx, EDolphinControllerType type,
const DolphinControllerState& state) {(void)idx;(void)type;(void)state;}
virtual void controllerUpdate(unsigned idx, EDolphinControllerType type, const DolphinControllerState& state) {
(void)idx;
(void)type;
(void)state;
}
};
class DolphinSmashAdapter final : public TDeviceBase<IDolphinSmashAdapterCallback>
{
class DolphinSmashAdapter final : public TDeviceBase<IDolphinSmashAdapterCallback> {
int16_t m_leftStickCal[2] = {0x7f};
int16_t m_rightStickCal[2] = {0x7f};
int16_t m_triggersCal[2] = {0x0};
@ -72,20 +71,26 @@ class DolphinSmashAdapter final : public TDeviceBase<IDolphinSmashAdapterCallbac
void initialCycle();
void transferCycle();
void finalCycle();
public:
DolphinSmashAdapter(DeviceToken* token);
~DolphinSmashAdapter();
void setCallback(IDolphinSmashAdapterCallback* cb)
{
void setCallback(IDolphinSmashAdapterCallback* cb) {
TDeviceBase<IDolphinSmashAdapterCallback>::setCallback(cb);
m_knownControllers = 0;
}
void startRumble(unsigned idx)
{if (idx >= 4) return; m_rumbleRequest |= 1<<idx;}
void stopRumble(unsigned idx, bool hard=false)
{if (idx >= 4) return; m_rumbleRequest &= ~(1<<idx); m_hardStop[idx] = hard;}
void startRumble(unsigned idx) {
if (idx >= 4)
return;
m_rumbleRequest |= 1 << idx;
}
void stopRumble(unsigned idx, bool hard = false) {
if (idx >= 4)
return;
m_rumbleRequest &= ~(1 << idx);
m_hardStop[idx] = hard;
}
};
}
} // namespace boo

View File

@ -4,11 +4,9 @@
#include "DeviceBase.hpp"
#include "boo/System.hpp"
namespace boo
{
namespace boo {
struct DualshockLED
{
struct DualshockLED {
uint8_t timeEnabled;
uint8_t dutyLength;
uint8_t enabled;
@ -16,8 +14,7 @@ struct DualshockLED
uint8_t dutyOn;
};
struct DualshockRumble
{
struct DualshockRumble {
uint8_t padding;
uint8_t rightDuration;
bool rightOn;
@ -25,10 +22,8 @@ struct DualshockRumble
uint8_t leftForce;
};
union DualshockOutReport
{
struct
{
union DualshockOutReport {
struct {
uint8_t reportId;
DualshockRumble rumble;
uint8_t gyro1;
@ -41,8 +36,7 @@ union DualshockOutReport
uint8_t buf[49];
};
enum class EDualshockPadButtons
{
enum class EDualshockPadButtons {
Select = 1 << 0,
L3 = 1 << 1,
R3 = 1 << 2,
@ -61,26 +55,17 @@ enum class EDualshockPadButtons
Square = 1 << 15
};
enum class EDualshockMotor : uint8_t
{
enum class EDualshockMotor : uint8_t {
None = 0,
Right = 1 << 0,
Left = 1 << 1,
};
ENABLE_BITWISE_ENUM(EDualshockMotor)
enum class EDualshockLED
{
LED_OFF = 0,
LED_1 = 1<<1,
LED_2 = 1<<2,
LED_3 = 1<<3,
LED_4 = 1<<4
};
enum class EDualshockLED { LED_OFF = 0, LED_1 = 1 << 1, LED_2 = 1 << 2, LED_3 = 1 << 3, LED_4 = 1 << 4 };
ENABLE_BITWISE_ENUM(EDualshockLED)
struct DualshockPadState
{
struct DualshockPadState {
uint8_t m_reportType;
uint8_t m_reserved1;
uint16_t m_buttonState;
@ -115,14 +100,12 @@ struct DualshockPadState
};
class DualshockPad;
struct IDualshockPadCallback
{
struct IDualshockPadCallback {
virtual void controllerDisconnected() {}
virtual void controllerUpdate(DualshockPad&, const DualshockPadState&) {}
};
class DualshockPad final : public TDeviceBase<IDualshockPadCallback>
{
class DualshockPad final : public TDeviceBase<IDualshockPadCallback> {
EDualshockMotor m_rumbleRequest;
EDualshockMotor m_rumbleState;
uint8_t m_rumbleDuration[2];
@ -134,37 +117,28 @@ class DualshockPad final : public TDeviceBase<IDualshockPadCallback>
void transferCycle();
void finalCycle();
void receivedHIDReport(const uint8_t* data, size_t length, HIDReportType tp, uint32_t message);
public:
DualshockPad(DeviceToken* token);
~DualshockPad();
void startRumble(EDualshockMotor motor, uint8_t duration = 254, uint8_t intensity=255)
{
void startRumble(EDualshockMotor motor, uint8_t duration = 254, uint8_t intensity = 255) {
m_rumbleRequest |= motor;
if ((EDualshockMotor(motor) & EDualshockMotor::Left) != EDualshockMotor::None)
{
if ((EDualshockMotor(motor) & EDualshockMotor::Left) != EDualshockMotor::None) {
m_rumbleDuration[0] = duration;
m_rumbleIntensity[0] = intensity;
}
if ((EDualshockMotor(motor) & EDualshockMotor::Right) != EDualshockMotor::None)
{
if ((EDualshockMotor(motor) & EDualshockMotor::Right) != EDualshockMotor::None) {
m_rumbleDuration[1] = duration;
m_rumbleIntensity[1] = intensity;
}
}
void stopRumble(int motor)
{
m_rumbleRequest &= ~EDualshockMotor(motor);
}
void stopRumble(int motor) { m_rumbleRequest &= ~EDualshockMotor(motor); }
EDualshockLED getLED()
{
return m_led;
}
EDualshockLED getLED() { return m_led; }
void setLED(EDualshockLED led, bool on = true)
{
void setLED(EDualshockLED led, bool on = true) {
if (on)
m_led |= led;
else
@ -173,12 +147,10 @@ public:
setRawLED(int(led));
}
void setRawLED(int led)
{
void setRawLED(int led) {
m_report.leds = led;
sendHIDReport(m_report.buf, sizeof(m_report), HIDReportType::Output, 0x01);
}
};
}
} // namespace boo

View File

@ -5,19 +5,17 @@
#include <map>
#include <mutex>
namespace boo
{
namespace boo {
struct IGenericPadCallback
{
struct IGenericPadCallback {
virtual void controllerConnected() {}
virtual void controllerDisconnected() {}
virtual void valueUpdate(const HIDMainItem& item, int32_t value) {}
};
class GenericPad final : public TDeviceBase<IGenericPadCallback>
{
class GenericPad final : public TDeviceBase<IGenericPadCallback> {
HIDParser m_parser;
public:
GenericPad(DeviceToken* token);
~GenericPad();
@ -29,5 +27,4 @@ public:
void enumerateValues(const std::function<bool(const HIDMainItem& item)>& valueCB) const;
};
}
} // namespace boo

View File

@ -10,14 +10,12 @@
#include <hidsdi.h>
#endif
namespace boo
{
namespace boo {
struct HIDItemState;
struct HIDCollectionItem;
struct HIDReports;
enum class HIDUsagePage : uint8_t
{
enum class HIDUsagePage : uint8_t {
Undefined = 0,
GenericDesktop = 1,
Simulation = 2,
@ -34,8 +32,7 @@ enum class HIDUsagePage : uint8_t
Digitizer = 13
};
enum class HIDUsage : uint8_t
{
enum class HIDUsage : uint8_t {
Undefined = 0,
/* Generic Desktop */
@ -142,8 +139,7 @@ enum class HIDUsage : uint8_t
using HIDRange = std::pair<int32_t, int32_t>;
/* [6.2.2.5] Input, Output, and Feature Items */
struct HIDMainItem
{
struct HIDMainItem {
uint16_t m_flags;
HIDUsagePage m_usagePage;
HIDUsage m_usage;
@ -161,23 +157,16 @@ struct HIDMainItem
HIDMainItem() = default;
HIDMainItem(uint32_t flags, const HIDItemState& state, uint32_t reportIdx);
HIDMainItem(uint32_t flags, HIDUsagePage usagePage, HIDUsage usage,
HIDRange logicalRange, int32_t reportSize);
HIDMainItem(uint32_t flags, HIDUsagePage usagePage, HIDUsage usage, HIDRange logicalRange, int32_t reportSize);
const char* GetUsagePageName() const;
const char* GetUsageName() const;
};
class HIDParser
{
class HIDParser {
public:
enum class ParserStatus
{
OK,
Done,
Error
};
private:
enum class ParserStatus { OK, Done, Error };
private:
ParserStatus m_status = ParserStatus::OK;
#if _WIN32
#if !WINDOWS_STORE
@ -193,10 +182,8 @@ private:
std::pair<uint32_t, uint32_t> m_outputReports = {};
std::pair<uint32_t, uint32_t> m_featureReports = {};
bool m_multipleReports = false;
static ParserStatus ParseItem(HIDReports& reportsOut,
std::stack<HIDItemState>& stateStack,
std::stack<HIDCollectionItem>& collectionStack,
const uint8_t*& it, const uint8_t* end,
static ParserStatus ParseItem(HIDReports& reportsOut, std::stack<HIDItemState>& stateStack,
std::stack<HIDCollectionItem>& collectionStack, const uint8_t*& it, const uint8_t* end,
bool& multipleReports);
#endif
@ -212,9 +199,8 @@ public:
#endif
operator bool() const { return m_status == ParserStatus::Done; }
void EnumerateValues(const std::function<bool(const HIDMainItem& item)>& valueCB) const;
void ScanValues(const std::function<bool(const HIDMainItem& item, int32_t value)>& valueCB,
const uint8_t* data, size_t len) const;
void ScanValues(const std::function<bool(const HIDMainItem& item, int32_t value)>& valueCB, const uint8_t* data,
size_t len) const;
};
}
} // namespace boo

View File

@ -4,15 +4,13 @@
#include <mutex>
#include "DeviceToken.hpp"
namespace boo
{
namespace boo {
typedef std::unordered_map<std::string, std::unique_ptr<DeviceToken>> TDeviceTokens;
typedef std::pair<TDeviceTokens::iterator, bool> TInsertedDeviceToken;
class DeviceFinder;
class IHIDListener
{
class IHIDListener {
public:
virtual ~IHIDListener() = default;
@ -28,11 +26,9 @@ public:
virtual bool _extDevConnect(const char* path) = 0;
virtual bool _extDevDisconnect(const char* path) = 0;
#endif
};
/* Platform-specific constructor */
std::unique_ptr<IHIDListener> IHIDListenerNew(DeviceFinder& finder);
}
} // namespace boo

View File

@ -2,10 +2,8 @@
#include "DeviceBase.hpp"
#include "boo/System.hpp"
namespace boo
{
struct NintendoPowerAState
{
namespace boo {
struct NintendoPowerAState {
uint8_t y : 1;
uint8_t b : 1;
uint8_t a : 1;
@ -30,23 +28,21 @@ struct NintendoPowerAState
};
class NintendoPowerA;
struct INintendoPowerACallback
{
struct INintendoPowerACallback {
virtual void controllerDisconnected() {}
virtual void controllerUpdate(const NintendoPowerAState& state) {}
};
class NintendoPowerA final : public TDeviceBase<INintendoPowerACallback>
{
class NintendoPowerA final : public TDeviceBase<INintendoPowerACallback> {
NintendoPowerAState m_last;
void deviceDisconnected();
void initialCycle();
void transferCycle();
void finalCycle();
void receivedHIDReport(const uint8_t* data, size_t length, HIDReportType tp, uint32_t message);
public:
NintendoPowerA(DeviceToken*);
~NintendoPowerA();
};
}
} // namespace boo

View File

@ -1,7 +1,3 @@
#pragma once
namespace boo
{
}
namespace boo {}

View File

@ -4,11 +4,9 @@
#include "DeviceSignature.hpp"
#include "boo/System.hpp"
namespace boo
{
namespace boo {
struct XInputPadState
{
struct XInputPadState {
uint16_t wButtons;
uint8_t bLeftTrigger;
uint8_t bRightTrigger;
@ -18,8 +16,7 @@ struct XInputPadState
int16_t sThumbRY;
};
enum class EXInputMotor : uint8_t
{
enum class EXInputMotor : uint8_t {
None = 0,
Right = 1 << 0,
Left = 1 << 1,
@ -27,34 +24,30 @@ enum class EXInputMotor : uint8_t
ENABLE_BITWISE_ENUM(EXInputMotor)
class XInputPad;
struct IXInputPadCallback
{
struct IXInputPadCallback {
virtual void controllerDisconnected() {}
virtual void controllerUpdate(XInputPad& pad, const XInputPadState&) {}
};
class XInputPad final : public TDeviceBase<IXInputPadCallback>
{
class XInputPad final : public TDeviceBase<IXInputPadCallback> {
friend class HIDListenerWinUSB;
uint16_t m_rumbleRequest[2] = {};
uint16_t m_rumbleState[2] = {};
public:
XInputPad(DeviceToken* token) : TDeviceBase<IXInputPadCallback>(dev_typeid(XInputPad), token) {}
void deviceDisconnected()
{
void deviceDisconnected() {
std::lock_guard<std::mutex> lk(m_callbackLock);
if (m_callback)
m_callback->controllerDisconnected();
}
void startRumble(EXInputMotor motors, uint16_t intensity)
{
void startRumble(EXInputMotor motors, uint16_t intensity) {
if ((motors & EXInputMotor::Left) != EXInputMotor::None)
m_rumbleRequest[0] = intensity;
if ((motors & EXInputMotor::Right) != EXInputMotor::None)
m_rumbleRequest[1] = intensity;
}
void stopRumble(EXInputMotor motors)
{
void stopRumble(EXInputMotor motors) {
if ((motors & EXInputMotor::Left) != EXInputMotor::None)
m_rumbleRequest[0] = 0;
if ((motors & EXInputMotor::Right) != EXInputMotor::None)
@ -62,5 +55,4 @@ public:
}
};
}
} // namespace boo

View File

@ -30,21 +30,16 @@ public:
}
}
static inline CFPointer<T> adopt(T CF_RELEASES_ARGUMENT ptr) {
return CFPointer<T>(ptr, CFPointer<T>::Adopt);
}
static inline CFPointer<T> adopt(T CF_RELEASES_ARGUMENT ptr) { return CFPointer<T>(ptr, CFPointer<T>::Adopt); }
T get() const {
return fromStorageType(storage);
}
T get() const { return fromStorageType(storage); }
CFPointer& operator=(CFPointer other) {
swap(other);
return *this;
}
T* operator&()
{
T* operator&() {
if (CFTypeRef pointer = storage) {
CFRelease(pointer);
}
@ -52,10 +47,8 @@ public:
}
operator bool() const { return storage != nullptr; }
void reset()
{
if (storage)
{
void reset() {
if (storage) {
CFRelease(storage);
storage = nullptr;
}
@ -67,17 +60,11 @@ private:
enum AdoptTag { Adopt };
CFPointer(T ptr, AdoptTag) : storage(toStorageType(ptr)) {}
inline CFTypeRef toStorageType(CFTypeRef ptr) const {
return (CFTypeRef)ptr;
}
inline CFTypeRef toStorageType(CFTypeRef ptr) const { return (CFTypeRef)ptr; }
inline T fromStorageType(CFTypeRef pointer) const {
return (T)pointer;
}
inline T fromStorageType(CFTypeRef pointer) const { return (T)pointer; }
void swap(CFPointer &other) {
std::swap(storage, other.storage);
}
void swap(CFPointer& other) { std::swap(storage, other.storage); }
};
/// A smart pointer that can manage the lifecycle of CoreFoundation IUnknown objects.
@ -116,13 +103,9 @@ public:
}
}
static inline IUnknownPointer<T> adopt(T** ptr) {
return IUnknownPointer<T>(ptr, IUnknownPointer<T>::Adopt);
}
static inline IUnknownPointer<T> adopt(T** ptr) { return IUnknownPointer<T>(ptr, IUnknownPointer<T>::Adopt); }
T* get() const {
return fromStorageType(_storage);
}
T* get() const { return fromStorageType(_storage); }
T* operator->() const { return get(); }
T** storage() const { return (T**)_storage; }
@ -140,16 +123,9 @@ private:
enum AdoptTag { Adopt };
IUnknownPointer(T** ptr, AdoptTag) : _storage(toStorageType(ptr)) {}
inline IUnknownVTbl** toStorageType(T** ptr) const {
return (IUnknownVTbl**)ptr;
}
inline IUnknownVTbl** toStorageType(T** ptr) const { return (IUnknownVTbl**)ptr; }
inline T* fromStorageType(IUnknownVTbl** pointer) const {
return *(T**)pointer;
}
inline T* fromStorageType(IUnknownVTbl** pointer) const { return *(T**)pointer; }
void swap(IUnknownPointer &other) {
std::swap(_storage, other._storage);
}
void swap(IUnknownPointer& other) { std::swap(_storage, other._storage); }
};

View File

@ -3,14 +3,13 @@
#include "boo/BooObject.hpp"
#include <iterator>
namespace boo
{
namespace boo {
/** Linked-list iterator shareable by ListNode types. */
template <class T>
class ListIterator
{
class ListIterator {
T* m_node;
public:
using iterator_category = std::bidirectional_iterator_tag;
using value_type = T;
@ -21,8 +20,14 @@ public:
explicit ListIterator(T* node) : m_node(node) {}
T& operator*() const { return *m_node; }
bool operator!=(const ListIterator& other) const { return m_node != other.m_node; }
ListIterator& operator++() { m_node = m_node->m_next; return *this; }
ListIterator& operator--() { m_node = m_node->m_prev; return *this; }
ListIterator& operator++() {
m_node = m_node->m_next;
return *this;
}
ListIterator& operator--() {
m_node = m_node->m_prev;
return *this;
}
};
/** Linked-list IObj node made part of objects participating in list.
@ -30,8 +35,7 @@ public:
* to support the common list-management functionality.
*/
template <class N, class H, class P = IObj>
struct ListNode : P
{
struct ListNode : P {
using iterator = ListIterator<N>;
iterator begin() { return iterator(static_cast<N*>(this)); }
iterator end() { return iterator(nullptr); }
@ -39,25 +43,21 @@ struct ListNode : P
H m_head;
N* m_next;
N* m_prev = nullptr;
ListNode(H head) : m_head(head)
{
ListNode(H head) : m_head(head) {
auto lk = N::_getHeadLock(head);
m_next = N::_getHeadPtr(head);
if (m_next)
m_next->m_prev = static_cast<N*>(this);
N::_getHeadPtr(head) = static_cast<N*>(this);
}
protected:
~ListNode()
{
if (m_prev)
{
~ListNode() {
if (m_prev) {
if (m_next)
m_next->m_prev = m_prev;
m_prev->m_next = m_next;
}
else
{
} else {
if (m_next)
m_next->m_prev = nullptr;
N::_getHeadPtr(m_head) = m_next;
@ -65,8 +65,7 @@ protected:
}
};
static inline uint32_t flp2(uint32_t x)
{
static inline uint32_t flp2(uint32_t x) {
x = x | (x >> 1);
x = x | (x >> 2);
x = x | (x >> 4);
@ -75,5 +74,4 @@ static inline uint32_t flp2(uint32_t x)
return x - (x >> 1);
}
}
} // namespace boo

View File

@ -10,16 +10,13 @@
#include <mutex>
#include <condition_variable>
namespace boo
{
namespace boo {
static logvisor::Module Log("boo::AQS");
#define AQS_NUM_BUFFERS 24
static AudioChannel AQSChannelToBooChannel(AudioChannelLabel ch)
{
switch (ch)
{
static AudioChannel AQSChannelToBooChannel(AudioChannelLabel ch) {
switch (ch) {
case kAudioChannelLabel_Left:
return AudioChannel::FrontLeft;
case kAudioChannelLabel_Right:
@ -40,8 +37,7 @@ static AudioChannel AQSChannelToBooChannel(AudioChannelLabel ch)
return AudioChannel::Unknown;
}
struct AQSAudioVoiceEngine : BaseAudioVoiceEngine
{
struct AQSAudioVoiceEngine : BaseAudioVoiceEngine {
CFPointer<CFStringRef> m_runLoopMode;
CFPointer<CFStringRef> m_devName;
@ -54,20 +50,17 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine
bool m_cbRunning = true;
bool m_needsRebuild = false;
static void Callback(AQSAudioVoiceEngine* engine, AudioQueueRef inAQ, AudioQueueBufferRef inBuffer)
{
static void Callback(AQSAudioVoiceEngine* engine, AudioQueueRef inAQ, AudioQueueBufferRef inBuffer) {
if (!engine->m_cbRunning)
return;
engine->_pumpAndMixVoices(engine->m_mixInfo.m_periodFrames,
reinterpret_cast<float*>(inBuffer->mAudioData));
engine->_pumpAndMixVoices(engine->m_mixInfo.m_periodFrames, reinterpret_cast<float*>(inBuffer->mAudioData));
inBuffer->mAudioDataByteSize = engine->m_frameBytes;
AudioQueueEnqueueBuffer(inAQ, inBuffer, 0, nullptr);
}
static void DummyCallback(AQSAudioVoiceEngine* engine, AudioQueueRef inAQ, AudioQueueBufferRef inBuffer) {}
std::pair<AudioChannelSet, Float64> _getAvailableSetAndRate()
{
std::pair<AudioChannelSet, Float64> _getAvailableSetAndRate() {
AudioObjectPropertyAddress propertyAddress;
UInt32 argSize;
int numStreams;
@ -79,7 +72,8 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine
propertyAddress.mScope = kAudioObjectPropertyScopeGlobal;
propertyAddress.mElement = kAudioObjectPropertyElementMaster;
argSize = sizeof(devId);
if (AudioObjectGetPropertyData(kAudioObjectSystemObject, &propertyAddress, sizeof(devName), &devName, &argSize, &devId) != noErr) {
if (AudioObjectGetPropertyData(kAudioObjectSystemObject, &propertyAddress, sizeof(devName), &devName, &argSize,
&devId) != noErr) {
Log.report(logvisor::Error, "unable to resolve audio device UID %s, using default",
CFStringGetCStringPtr(devName, kCFStringEncodingUTF8));
argSize = sizeof(devId);
@ -111,8 +105,7 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine
AudioStreamBasicDescription asbd;
argSize = sizeof(asbd);
if (AudioObjectGetPropertyData(streamIDs[stm], &propertyAddress, 0, NULL, &argSize, &asbd) == noErr) {
switch (asbd.mChannelsPerFrame)
{
switch (asbd.mChannelsPerFrame) {
case 2:
return {AudioChannelSet::Stereo, asbd.mSampleRate};
case 4:
@ -121,7 +114,8 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine
return {AudioChannelSet::Surround51, asbd.mSampleRate};
case 8:
return {AudioChannelSet::Surround71, asbd.mSampleRate};
default: break;
default:
break;
}
if (asbd.mChannelsPerFrame > 8)
return {AudioChannelSet::Surround71, asbd.mSampleRate};
@ -136,13 +130,9 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine
return {AudioChannelSet::Unknown, 48000.0};
}
std::string getCurrentAudioOutput() const
{
return CFStringGetCStringPtr(m_devName.get(), kCFStringEncodingUTF8);
}
std::string getCurrentAudioOutput() const { return CFStringGetCStringPtr(m_devName.get(), kCFStringEncodingUTF8); }
bool setCurrentAudioOutput(const char* name)
{
bool setCurrentAudioOutput(const char* name) {
m_devName = CFPointer<CFStringRef>::adopt(CFStringCreateWithCString(nullptr, name, kCFStringEncodingUTF8));
_rebuildAudioQueue();
return true;
@ -151,8 +141,7 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine
/*
* https://stackoverflow.com/questions/1983984/how-to-get-audio-device-uid-to-pass-into-nssounds-setplaybackdeviceidentifier
*/
std::vector<std::pair<std::string, std::string>> enumerateAudioOutputs() const
{
std::vector<std::pair<std::string, std::string>> enumerateAudioOutputs() const {
std::vector<std::pair<std::string, std::string>> ret;
AudioObjectPropertyAddress propertyAddress;
@ -171,7 +160,8 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine
ret.reserve(numDevices);
deviceIDs.resize(numDevices);
if (AudioObjectGetPropertyData(kAudioObjectSystemObject, &propertyAddress, 0, NULL, &propertySize, &deviceIDs[0]) == noErr) {
if (AudioObjectGetPropertyData(kAudioObjectSystemObject, &propertyAddress, 0, NULL, &propertySize,
&deviceIDs[0]) == noErr) {
char deviceName[64];
for (int idx = 0; idx < numDevices; idx++) {
@ -180,13 +170,15 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine
numStreams = propertySize / sizeof(AudioStreamID);
streamIDs.resize(numStreams);
if (AudioObjectGetPropertyData(deviceIDs[idx], &propertyAddress, 0, NULL, &propertySize, &streamIDs[0]) == noErr) {
if (AudioObjectGetPropertyData(deviceIDs[idx], &propertyAddress, 0, NULL, &propertySize, &streamIDs[0]) ==
noErr) {
propertyAddress.mSelector = kAudioStreamPropertyDirection;
bool foundOutput = false;
for (int stm = 0; stm < numStreams; stm++) {
UInt32 streamDir;
propertySize = sizeof(streamDir);
if (AudioObjectGetPropertyData(streamIDs[stm], &propertyAddress, 0, NULL, &propertySize, &streamDir) == noErr) {
if (AudioObjectGetPropertyData(streamIDs[stm], &propertyAddress, 0, NULL, &propertySize, &streamDir) ==
noErr) {
if (streamDir == 0) {
foundOutput = true;
break;
@ -200,12 +192,14 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine
propertySize = sizeof(deviceName);
propertyAddress.mSelector = kAudioDevicePropertyDeviceName;
if (AudioObjectGetPropertyData(deviceIDs[idx], &propertyAddress, 0, NULL, &propertySize, deviceName) == noErr) {
if (AudioObjectGetPropertyData(deviceIDs[idx], &propertyAddress, 0, NULL, &propertySize, deviceName) ==
noErr) {
CFPointer<CFStringRef> uidString;
propertySize = sizeof(CFStringRef);
propertyAddress.mSelector = kAudioDevicePropertyDeviceUID;
if (AudioObjectGetPropertyData(deviceIDs[idx], &propertyAddress, 0, NULL, &propertySize, &uidString) == noErr) {
if (AudioObjectGetPropertyData(deviceIDs[idx], &propertyAddress, 0, NULL, &propertySize, &uidString) ==
noErr) {
ret.emplace_back(CFStringGetCStringPtr(uidString.get(), kCFStringEncodingUTF8), deviceName);
}
}
@ -216,8 +210,7 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine
return ret;
}
std::vector<std::pair<std::string, std::string>> enumerateMIDIInputs() const
{
std::vector<std::pair<std::string, std::string>> enumerateMIDIInputs() const {
if (!m_midiClient)
return {};
@ -225,22 +218,18 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine
ItemCount numDevices = MIDIGetNumberOfDevices();
ret.reserve(numDevices);
for (int i=int(numDevices)-1 ; i>=0 ; --i)
{
for (int i = int(numDevices) - 1; i >= 0; --i) {
MIDIDeviceRef dev = MIDIGetDevice(i);
if (!dev)
continue;
bool isInput = false;
ItemCount numEnt = MIDIDeviceGetNumberOfEntities(dev);
for (ItemCount j=0 ; j<numEnt ; ++j)
{
for (ItemCount j = 0; j < numEnt; ++j) {
MIDIEntityRef ent = MIDIDeviceGetEntity(dev, j);
if (ent)
{
if (ent) {
ItemCount numSrc = MIDIEntityGetNumberOfSources(ent);
if (numSrc)
{
if (numSrc) {
isInput = true;
break;
}
@ -263,23 +252,17 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine
char idStr[9];
snprintf(idStr, 9, "%08X\n", idNum);
ret.push_back(std::make_pair(std::string(idStr),
std::string(nameCstr)));
ret.push_back(std::make_pair(std::string(idStr), std::string(nameCstr)));
}
return ret;
}
bool supportsVirtualMIDIIn() const
{
return true;
}
bool supportsVirtualMIDIIn() const { return true; }
static MIDIDeviceRef LookupMIDIDevice(const char* name)
{
static MIDIDeviceRef LookupMIDIDevice(const char* name) {
ItemCount numDevices = MIDIGetNumberOfDevices();
for (ItemCount i=0 ; i<numDevices ; ++i)
{
for (ItemCount i = 0; i < numDevices; ++i) {
MIDIDeviceRef dev = MIDIGetDevice(i);
if (!dev)
continue;
@ -299,21 +282,17 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine
return {};
}
static MIDIEndpointRef LookupMIDISource(const char* name)
{
static MIDIEndpointRef LookupMIDISource(const char* name) {
MIDIDeviceRef dev = LookupMIDIDevice(name);
if (!dev)
return {};
ItemCount numEnt = MIDIDeviceGetNumberOfEntities(dev);
for (ItemCount i=0 ; i<numEnt ; ++i)
{
for (ItemCount i = 0; i < numEnt; ++i) {
MIDIEntityRef ent = MIDIDeviceGetEntity(dev, i);
if (ent)
{
if (ent) {
ItemCount numSrc = MIDIEntityGetNumberOfSources(ent);
for (ItemCount s=0 ; s<numSrc ; ++s)
{
for (ItemCount s = 0; s < numSrc; ++s) {
MIDIEndpointRef src = MIDIEntityGetSource(ent, s);
if (src)
return src;
@ -324,21 +303,17 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine
return {};
}
static MIDIEndpointRef LookupMIDIDest(const char* name)
{
static MIDIEndpointRef LookupMIDIDest(const char* name) {
MIDIDeviceRef dev = LookupMIDIDevice(name);
if (!dev)
return {};
ItemCount numEnt = MIDIDeviceGetNumberOfEntities(dev);
for (ItemCount i=0 ; i<numEnt ; ++i)
{
for (ItemCount i = 0; i < numEnt; ++i) {
MIDIEntityRef ent = MIDIDeviceGetEntity(dev, i);
if (ent)
{
if (ent) {
ItemCount numDest = MIDIEntityGetNumberOfDestinations(ent);
for (ItemCount d=0 ; d<numDest ; ++d)
{
for (ItemCount d = 0; d < numDest; ++d) {
MIDIEndpointRef dst = MIDIEntityGetDestination(ent, d);
if (dst)
return dst;
@ -349,37 +324,30 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine
return {};
}
static void MIDIReceiveProc(const MIDIPacketList* pktlist,
IMIDIReceiver* readProcRefCon,
void*)
{
static void MIDIReceiveProc(const MIDIPacketList* pktlist, IMIDIReceiver* readProcRefCon, void*) {
const MIDIPacket* packet = &pktlist->packet[0];
for (int i=0 ; i<pktlist->numPackets ; ++i)
{
for (int i = 0; i < pktlist->numPackets; ++i) {
std::vector<uint8_t> bytes(std::cbegin(packet->data), std::cbegin(packet->data) + packet->length);
readProcRefCon->m_receiver(std::move(bytes), AudioConvertHostTimeToNanos(packet->timeStamp) / 1.0e9);
packet = MIDIPacketNext(packet);
}
}
struct MIDIIn : public IMIDIIn
{
struct MIDIIn : public IMIDIIn {
MIDIEndpointRef m_midi = 0;
MIDIPortRef m_midiPort = 0;
MIDIIn(AQSAudioVoiceEngine* parent, bool virt, ReceiveFunctor&& receiver)
: IMIDIIn(parent, virt, std::move(receiver)) {}
~MIDIIn()
{
~MIDIIn() {
if (m_midi)
MIDIEndpointDispose(m_midi);
if (m_midiPort)
MIDIPortDispose(m_midiPort);
}
std::string description() const
{
std::string description() const {
CFPointer<CFStringRef> namestr;
const char* nameCstr;
if (MIDIObjectGetStringProperty(m_midi, kMIDIPropertyName, &namestr))
@ -392,24 +360,20 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine
}
};
struct MIDIOut : public IMIDIOut
{
struct MIDIOut : public IMIDIOut {
MIDIEndpointRef m_midi = 0;
MIDIPortRef m_midiPort = 0;
MIDIOut(AQSAudioVoiceEngine* parent, bool virt)
: IMIDIOut(parent, virt) {}
MIDIOut(AQSAudioVoiceEngine* parent, bool virt) : IMIDIOut(parent, virt) {}
~MIDIOut()
{
~MIDIOut() {
if (m_midi)
MIDIEndpointDispose(m_midi);
if (m_midiPort)
MIDIPortDispose(m_midiPort);
}
std::string description() const
{
std::string description() const {
CFPointer<CFStringRef> namestr;
const char* nameCstr;
if (MIDIObjectGetStringProperty(m_midi, kMIDIPropertyName, &namestr))
@ -421,17 +385,14 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine
return nameCstr;
}
size_t send(const void* buf, size_t len) const
{
union
{
size_t send(const void* buf, size_t len) const {
union {
MIDIPacketList head;
Byte storage[512];
} list;
MIDIPacket* curPacket = MIDIPacketListInit(&list.head);
if (MIDIPacketListAdd(&list.head, sizeof(list), curPacket, AudioGetCurrentHostTime(),
len, reinterpret_cast<const Byte*>(buf)))
{
if (MIDIPacketListAdd(&list.head, sizeof(list), curPacket, AudioGetCurrentHostTime(), len,
reinterpret_cast<const Byte*>(buf))) {
if (m_midiPort)
MIDISend(m_midiPort, m_midi, &list.head);
else
@ -442,8 +403,7 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine
}
};
struct MIDIInOut : public IMIDIInOut
{
struct MIDIInOut : public IMIDIInOut {
MIDIEndpointRef m_midiIn = 0;
MIDIPortRef m_midiPortIn = 0;
MIDIEndpointRef m_midiOut = 0;
@ -452,8 +412,7 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine
MIDIInOut(AQSAudioVoiceEngine* parent, bool virt, ReceiveFunctor&& receiver)
: IMIDIInOut(parent, virt, std::move(receiver)) {}
~MIDIInOut()
{
~MIDIInOut() {
if (m_midiIn)
MIDIEndpointDispose(m_midiIn);
if (m_midiPortIn)
@ -464,8 +423,7 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine
MIDIPortDispose(m_midiPortOut);
}
std::string description() const
{
std::string description() const {
CFPointer<CFStringRef> namestr;
const char* nameCstr;
if (MIDIObjectGetStringProperty(m_midiIn, kMIDIPropertyName, &namestr))
@ -477,17 +435,14 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine
return nameCstr;
}
size_t send(const void* buf, size_t len) const
{
union
{
size_t send(const void* buf, size_t len) const {
union {
MIDIPacketList head;
Byte storage[512];
} list;
MIDIPacket* curPacket = MIDIPacketListInit(&list.head);
if (MIDIPacketListAdd(&list.head, sizeof(list), curPacket, AudioGetCurrentHostTime(),
len, reinterpret_cast<const Byte*>(buf)))
{
if (MIDIPacketListAdd(&list.head, sizeof(list), curPacket, AudioGetCurrentHostTime(), len,
reinterpret_cast<const Byte*>(buf))) {
if (m_midiPortOut)
MIDISend(m_midiPortOut, m_midiOut, &list.head);
else
@ -501,8 +456,7 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine
unsigned m_midiInCounter = 0;
unsigned m_midiOutCounter = 0;
std::unique_ptr<IMIDIIn> newVirtualMIDIIn(ReceiveFunctor&& receiver)
{
std::unique_ptr<IMIDIIn> newVirtualMIDIIn(ReceiveFunctor&& receiver) {
if (!m_midiClient)
return {};
@ -521,15 +475,13 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine
CFStringCreateWithCStringNoCopy(nullptr, name, kCFStringEncodingUTF8, kCFAllocatorNull));
OSStatus stat;
if ((stat = MIDIDestinationCreate(m_midiClient, midiName.get(), MIDIReadProc(MIDIReceiveProc),
static_cast<IMIDIReceiver*>(ret.get()),
&static_cast<MIDIIn&>(*ret).m_midi)))
static_cast<IMIDIReceiver*>(ret.get()), &static_cast<MIDIIn&>(*ret).m_midi)))
ret.reset();
return ret;
}
std::unique_ptr<IMIDIOut> newVirtualMIDIOut()
{
std::unique_ptr<IMIDIOut> newVirtualMIDIOut() {
if (!m_midiClient)
return {};
@ -552,8 +504,7 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine
return ret;
}
std::unique_ptr<IMIDIInOut> newVirtualMIDIInOut(ReceiveFunctor&& receiver)
{
std::unique_ptr<IMIDIInOut> newVirtualMIDIInOut(ReceiveFunctor&& receiver) {
if (!m_midiClient)
return {};
@ -571,8 +522,7 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine
CFPointer<CFStringRef> midiName = CFPointer<CFStringRef>::adopt(
CFStringCreateWithCStringNoCopy(nullptr, name, kCFStringEncodingUTF8, kCFAllocatorNull));
if (MIDIDestinationCreate(m_midiClient, midiName.get(), MIDIReadProc(MIDIReceiveProc),
static_cast<IMIDIReceiver*>(ret.get()),
&static_cast<MIDIInOut&>(*ret).m_midiIn))
static_cast<IMIDIReceiver*>(ret.get()), &static_cast<MIDIInOut&>(*ret).m_midiIn))
ret.reset();
if (!ret)
@ -591,8 +541,7 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine
return ret;
}
std::unique_ptr<IMIDIIn> newRealMIDIIn(const char* name, ReceiveFunctor&& receiver)
{
std::unique_ptr<IMIDIIn> newRealMIDIIn(const char* name, ReceiveFunctor&& receiver) {
if (!m_midiClient)
return {};
@ -609,8 +558,7 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine
CFPointer<CFStringRef> midiName = CFPointer<CFStringRef>::adopt(
CFStringCreateWithCStringNoCopy(nullptr, mname, kCFStringEncodingUTF8, kCFAllocatorNull));
if (MIDIInputPortCreate(m_midiClient, midiName.get(), MIDIReadProc(MIDIReceiveProc),
static_cast<IMIDIReceiver*>(ret.get()),
&static_cast<MIDIIn&>(*ret).m_midiPort))
static_cast<IMIDIReceiver*>(ret.get()), &static_cast<MIDIIn&>(*ret).m_midiPort))
ret.reset();
else
MIDIPortConnectSource(static_cast<MIDIIn&>(*ret).m_midiPort, src, nullptr);
@ -618,8 +566,7 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine
return ret;
}
std::unique_ptr<IMIDIOut> newRealMIDIOut(const char* name)
{
std::unique_ptr<IMIDIOut> newRealMIDIOut(const char* name) {
if (!m_midiClient)
return {};
@ -643,8 +590,7 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine
return ret;
}
std::unique_ptr<IMIDIInOut> newRealMIDIInOut(const char* name, ReceiveFunctor&& receiver)
{
std::unique_ptr<IMIDIInOut> newRealMIDIInOut(const char* name, ReceiveFunctor&& receiver) {
if (!m_midiClient)
return {};
@ -665,8 +611,7 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine
CFPointer<CFStringRef> midiName = CFPointer<CFStringRef>::adopt(
CFStringCreateWithCStringNoCopy(nullptr, mname, kCFStringEncodingUTF8, kCFAllocatorNull));
if (MIDIInputPortCreate(m_midiClient, midiName.get(), MIDIReadProc(MIDIReceiveProc),
static_cast<IMIDIReceiver*>(ret.get()),
&static_cast<MIDIInOut&>(*ret).m_midiPortIn))
static_cast<IMIDIReceiver*>(ret.get()), &static_cast<MIDIInOut&>(*ret).m_midiPortIn))
ret.reset();
else
MIDIPortConnectSource(static_cast<MIDIInOut&>(*ret).m_midiPortIn, src, nullptr);
@ -687,17 +632,12 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine
bool useMIDILock() const { return true; }
static void SampleRateChanged(AQSAudioVoiceEngine* engine,
AudioQueueRef inAQ,
AudioQueuePropertyID inID)
{
static void SampleRateChanged(AQSAudioVoiceEngine* engine, AudioQueueRef inAQ, AudioQueuePropertyID inID) {
engine->m_needsRebuild = true;
}
void _rebuildAudioQueue()
{
if (m_queue)
{
void _rebuildAudioQueue() {
if (m_queue) {
m_cbRunning = false;
AudioQueueDispose(m_queue, true);
m_cbRunning = true;
@ -719,16 +659,14 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine
desc.mBitsPerChannel = 32;
OSStatus err;
if ((err = AudioQueueNewOutput(&desc, AudioQueueOutputCallback(Callback),
this, CFRunLoopGetCurrent(), m_runLoopMode.get(), 0, &m_queue)))
{
if ((err = AudioQueueNewOutput(&desc, AudioQueueOutputCallback(Callback), this, CFRunLoopGetCurrent(),
m_runLoopMode.get(), 0, &m_queue))) {
Log.report(logvisor::Fatal, "unable to create output audio queue");
return;
}
CFStringRef devName = m_devName.get();
if ((err = AudioQueueSetProperty(m_queue, kAudioQueueProperty_CurrentDevice, &devName, sizeof(devName))))
{
if ((err = AudioQueueSetProperty(m_queue, kAudioQueueProperty_CurrentDevice, &devName, sizeof(devName)))) {
Log.report(logvisor::Fatal, "unable to set current device into audio queue");
return;
}
@ -743,15 +681,12 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine
ChannelMap& chMapOut = m_mixInfo.m_channelMap;
chMapOut.m_channelCount = 0;
if (chCount > 2)
{
if (chCount > 2) {
AudioChannelLayout layout;
UInt32 layoutSz = sizeof(layout);
if (AudioQueueGetProperty(m_queue, kAudioQueueProperty_ChannelLayout, &layout, &layoutSz))
{
if (AudioQueueGetProperty(m_queue, kAudioQueueProperty_ChannelLayout, &layout, &layoutSz)) {
Log.report(logvisor::Warning, "unable to get channel layout from audio queue; using count's default");
switch (m_mixInfo.m_channels)
{
switch (m_mixInfo.m_channels) {
case AudioChannelSet::Stereo:
default:
chMapOut.m_channels[chMapOut.m_channelCount++] = AudioChannel::FrontLeft;
@ -782,15 +717,11 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine
chMapOut.m_channels[chMapOut.m_channelCount++] = AudioChannel::RearRight;
break;
}
}
else
{
switch (layout.mChannelLayoutTag)
{
} else {
switch (layout.mChannelLayoutTag) {
case kAudioChannelLayoutTag_UseChannelDescriptions:
chMapOut.m_channelCount = layout.mNumberChannelDescriptions;
for (int i = 0; i < layout.mNumberChannelDescriptions; ++i)
{
for (int i = 0; i < layout.mNumberChannelDescriptions; ++i) {
AudioChannel ch = AQSChannelToBooChannel(layout.mChannelDescriptions[i].mChannelLabel);
chMapOut.m_channels[i] = ch;
}
@ -835,18 +766,14 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine
chMapOut.m_channels[4] = AudioChannel::FrontCenter;
break;
default:
Log.report(logvisor::Warning,
"unknown channel layout %u; using stereo",
layout.mChannelLayoutTag);
Log.report(logvisor::Warning, "unknown channel layout %u; using stereo", layout.mChannelLayoutTag);
chMapOut.m_channelCount = 2;
chMapOut.m_channels[0] = AudioChannel::FrontLeft;
chMapOut.m_channels[1] = AudioChannel::FrontRight;
break;
}
}
}
else
{
} else {
chMapOut.m_channels[chMapOut.m_channelCount++] = AudioChannel::FrontLeft;
chMapOut.m_channels[chMapOut.m_channelCount++] = AudioChannel::FrontRight;
}
@ -856,8 +783,7 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine
m_mixInfo.m_periodFrames = m_5msFrames;
for (int i = 0; i < AQS_NUM_BUFFERS; ++i)
if (AudioQueueAllocateBuffer(m_queue, m_mixInfo.m_periodFrames * chCount * 4, &m_buffers[i]))
{
if (AudioQueueAllocateBuffer(m_queue, m_mixInfo.m_periodFrames * chCount * 4, &m_buffers[i])) {
Log.report(logvisor::Fatal, "unable to create audio queue buffer");
AudioQueueDispose(m_queue, false);
m_queue = nullptr;
@ -868,8 +794,7 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine
_resetSampleRate();
for (unsigned i=0 ; i<AQS_NUM_BUFFERS ; ++i)
{
for (unsigned i = 0; i < AQS_NUM_BUFFERS; ++i) {
memset(m_buffers[i]->mAudioData, 0, m_frameBytes);
m_buffers[i]->mAudioDataByteSize = m_frameBytes;
AudioQueueEnqueueBuffer(m_queue, m_buffers[i], 0, nullptr);
@ -878,11 +803,8 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine
AudioQueueStart(m_queue, nullptr);
}
static OSStatus AudioDeviceChanged(AudioObjectID inObjectID,
UInt32 inNumberAddresses,
const AudioObjectPropertyAddress* inAddresses,
AQSAudioVoiceEngine* engine)
{
static OSStatus AudioDeviceChanged(AudioObjectID inObjectID, UInt32 inNumberAddresses,
const AudioObjectPropertyAddress* inAddresses, AQSAudioVoiceEngine* engine) {
AudioObjectID defaultDeviceId;
UInt32 argSize = sizeof(defaultDeviceId);
if (AudioObjectGetPropertyData(inObjectID, inAddresses, 0, NULL, &argSize, &defaultDeviceId) == noErr) {
@ -897,8 +819,7 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine
AQSAudioVoiceEngine()
: m_runLoopMode(CFPointer<CFStringRef>::adopt(
CFStringCreateWithCStringNoCopy(nullptr, "BooAQSMode", kCFStringEncodingUTF8, kCFAllocatorNull)))
{
CFStringCreateWithCStringNoCopy(nullptr, "BooAQSMode", kCFStringEncodingUTF8, kCFAllocatorNull))) {
AudioObjectPropertyAddress propertyAddress;
propertyAddress.mScope = kAudioObjectPropertyScopeGlobal;
propertyAddress.mElement = kAudioObjectPropertyElementMaster;
@ -906,7 +827,8 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine
AudioObjectID defaultDeviceId;
UInt32 argSize = sizeof(defaultDeviceId);
propertyAddress.mSelector = kAudioHardwarePropertyDefaultOutputDevice;
if (AudioObjectGetPropertyData(kAudioObjectSystemObject, &propertyAddress, 0, NULL, &argSize, &defaultDeviceId) == noErr) {
if (AudioObjectGetPropertyData(kAudioObjectSystemObject, &propertyAddress, 0, NULL, &argSize, &defaultDeviceId) ==
noErr) {
argSize = sizeof(CFStringRef);
AudioObjectPropertyAddress deviceAddress;
deviceAddress.mSelector = kAudioDevicePropertyDeviceUID;
@ -926,31 +848,27 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine
MIDIClientCreate(CFSTR("Boo MIDI"), nullptr, nullptr, &m_midiClient);
}
~AQSAudioVoiceEngine()
{
~AQSAudioVoiceEngine() {
m_cbRunning = false;
AudioQueueDispose(m_queue, true);
if (m_midiClient)
MIDIClientDispose(m_midiClient);
}
void pumpAndMixVoices()
{
void pumpAndMixVoices() {
while (CFRunLoopRunInMode(m_runLoopMode.get(), 0, true) == kCFRunLoopRunHandledSource) {}
if (m_needsRebuild)
{
if (m_needsRebuild) {
_rebuildAudioQueue();
m_needsRebuild = false;
}
}
};
std::unique_ptr<IAudioVoiceEngine> NewAudioVoiceEngine()
{
std::unique_ptr<IAudioVoiceEngine> NewAudioVoiceEngine() {
std::unique_ptr<IAudioVoiceEngine> ret = std::make_unique<AQSAudioVoiceEngine>();
if (!static_cast<AQSAudioVoiceEngine&>(*ret).m_queue)
return {};
return ret;
}
}
} // namespace boo

View File

@ -2,16 +2,13 @@
#include "AudioVoiceEngine.hpp"
#include <cstring>
namespace boo
{
namespace boo {
void AudioMatrixMono::setDefaultMatrixCoefficients(AudioChannelSet acSet)
{
void AudioMatrixMono::setDefaultMatrixCoefficients(AudioChannelSet acSet) {
m_curSlewFrame = 0;
m_slewFrames = 0;
memset(&m_coefs, 0, sizeof(m_coefs));
switch (acSet)
{
switch (acSet) {
case AudioChannelSet::Stereo:
case AudioChannelSet::Quad:
m_coefs.v[int(AudioChannel::FrontLeft)] = 1.0;
@ -21,40 +18,32 @@ void AudioMatrixMono::setDefaultMatrixCoefficients(AudioChannelSet acSet)
case AudioChannelSet::Surround71:
m_coefs.v[int(AudioChannel::FrontCenter)] = 1.0;
break;
default: break;
default:
break;
}
}
int16_t* AudioMatrixMono::mixMonoSampleData(const AudioVoiceEngineMixInfo& info,
const int16_t* dataIn, int16_t* dataOut, size_t samples)
{
int16_t* AudioMatrixMono::mixMonoSampleData(const AudioVoiceEngineMixInfo& info, const int16_t* dataIn,
int16_t* dataOut, size_t samples) {
const ChannelMap& chmap = info.m_channelMap;
for (size_t s=0 ; s<samples ; ++s, ++dataIn)
{
if (m_slewFrames && m_curSlewFrame < m_slewFrames)
{
for (size_t s = 0; s < samples; ++s, ++dataIn) {
if (m_slewFrames && m_curSlewFrame < m_slewFrames) {
double t = m_curSlewFrame / double(m_slewFrames);
double omt = 1.0 - t;
for (unsigned c=0 ; c<chmap.m_channelCount ; ++c)
{
for (unsigned c = 0; c < chmap.m_channelCount; ++c) {
AudioChannel ch = chmap.m_channels[c];
if (ch != AudioChannel::Unknown)
{
if (ch != AudioChannel::Unknown) {
*dataOut = Clamp16(*dataOut + *dataIn * (m_coefs.v[int(ch)] * t + m_oldCoefs.v[int(ch)] * omt));
++dataOut;
}
}
++m_curSlewFrame;
}
else
{
for (unsigned c=0 ; c<chmap.m_channelCount ; ++c)
{
} else {
for (unsigned c = 0; c < chmap.m_channelCount; ++c) {
AudioChannel ch = chmap.m_channels[c];
if (ch != AudioChannel::Unknown)
{
if (ch != AudioChannel::Unknown) {
*dataOut = Clamp16(*dataOut + *dataIn * m_coefs.v[int(ch)]);
++dataOut;
}
@ -64,36 +53,27 @@ int16_t* AudioMatrixMono::mixMonoSampleData(const AudioVoiceEngineMixInfo& info,
return dataOut;
}
int32_t* AudioMatrixMono::mixMonoSampleData(const AudioVoiceEngineMixInfo& info,
const int32_t* dataIn, int32_t* dataOut, size_t samples)
{
int32_t* AudioMatrixMono::mixMonoSampleData(const AudioVoiceEngineMixInfo& info, const int32_t* dataIn,
int32_t* dataOut, size_t samples) {
const ChannelMap& chmap = info.m_channelMap;
for (size_t s=0 ; s<samples ; ++s, ++dataIn)
{
if (m_slewFrames && m_curSlewFrame < m_slewFrames)
{
for (size_t s = 0; s < samples; ++s, ++dataIn) {
if (m_slewFrames && m_curSlewFrame < m_slewFrames) {
double t = m_curSlewFrame / double(m_slewFrames);
double omt = 1.0 - t;
for (unsigned c=0 ; c<chmap.m_channelCount ; ++c)
{
for (unsigned c = 0; c < chmap.m_channelCount; ++c) {
AudioChannel ch = chmap.m_channels[c];
if (ch != AudioChannel::Unknown)
{
if (ch != AudioChannel::Unknown) {
*dataOut = Clamp32(*dataOut + *dataIn * (m_coefs.v[int(ch)] * t + m_oldCoefs.v[int(ch)] * omt));
++dataOut;
}
}
++m_curSlewFrame;
}
else
{
for (unsigned c=0 ; c<chmap.m_channelCount ; ++c)
{
} else {
for (unsigned c = 0; c < chmap.m_channelCount; ++c) {
AudioChannel ch = chmap.m_channels[c];
if (ch != AudioChannel::Unknown)
{
if (ch != AudioChannel::Unknown) {
*dataOut = Clamp32(*dataOut + *dataIn * m_coefs.v[int(ch)]);
++dataOut;
}
@ -103,36 +83,27 @@ int32_t* AudioMatrixMono::mixMonoSampleData(const AudioVoiceEngineMixInfo& info,
return dataOut;
}
float* AudioMatrixMono::mixMonoSampleData(const AudioVoiceEngineMixInfo& info,
const float* dataIn, float* dataOut, size_t samples)
{
float* AudioMatrixMono::mixMonoSampleData(const AudioVoiceEngineMixInfo& info, const float* dataIn, float* dataOut,
size_t samples) {
const ChannelMap& chmap = info.m_channelMap;
for (size_t s=0 ; s<samples ; ++s, ++dataIn)
{
if (m_slewFrames && m_curSlewFrame < m_slewFrames)
{
for (size_t s = 0; s < samples; ++s, ++dataIn) {
if (m_slewFrames && m_curSlewFrame < m_slewFrames) {
double t = m_curSlewFrame / double(m_slewFrames);
double omt = 1.0 - t;
for (unsigned c=0 ; c<chmap.m_channelCount ; ++c)
{
for (unsigned c = 0; c < chmap.m_channelCount; ++c) {
AudioChannel ch = chmap.m_channels[c];
if (ch != AudioChannel::Unknown)
{
if (ch != AudioChannel::Unknown) {
*dataOut = *dataOut + *dataIn * (m_coefs.v[int(ch)] * t + m_oldCoefs.v[int(ch)] * omt);
++dataOut;
}
}
++m_curSlewFrame;
}
else
{
for (unsigned c=0 ; c<chmap.m_channelCount ; ++c)
{
} else {
for (unsigned c = 0; c < chmap.m_channelCount; ++c) {
AudioChannel ch = chmap.m_channels[c];
if (ch != AudioChannel::Unknown)
{
if (ch != AudioChannel::Unknown) {
*dataOut = *dataOut + *dataIn * m_coefs.v[int(ch)];
++dataOut;
}
@ -142,13 +113,11 @@ float* AudioMatrixMono::mixMonoSampleData(const AudioVoiceEngineMixInfo& info,
return dataOut;
}
void AudioMatrixStereo::setDefaultMatrixCoefficients(AudioChannelSet acSet)
{
void AudioMatrixStereo::setDefaultMatrixCoefficients(AudioChannelSet acSet) {
m_curSlewFrame = 0;
m_slewFrames = 0;
memset(&m_coefs, 0, sizeof(m_coefs));
switch (acSet)
{
switch (acSet) {
case AudioChannelSet::Stereo:
case AudioChannelSet::Quad:
m_coefs.v[int(AudioChannel::FrontLeft)][0] = 1.0;
@ -159,45 +128,34 @@ void AudioMatrixStereo::setDefaultMatrixCoefficients(AudioChannelSet acSet)
m_coefs.v[int(AudioChannel::FrontLeft)][0] = 1.0;
m_coefs.v[int(AudioChannel::FrontRight)][1] = 1.0;
break;
default: break;
default:
break;
}
}
int16_t* AudioMatrixStereo::mixStereoSampleData(const AudioVoiceEngineMixInfo& info,
const int16_t* dataIn, int16_t* dataOut, size_t frames)
{
int16_t* AudioMatrixStereo::mixStereoSampleData(const AudioVoiceEngineMixInfo& info, const int16_t* dataIn,
int16_t* dataOut, size_t frames) {
const ChannelMap& chmap = info.m_channelMap;
for (size_t f=0 ; f<frames ; ++f, dataIn += 2)
{
if (m_slewFrames && m_curSlewFrame < m_slewFrames)
{
for (size_t f = 0; f < frames; ++f, dataIn += 2) {
if (m_slewFrames && m_curSlewFrame < m_slewFrames) {
double t = m_curSlewFrame / double(m_slewFrames);
double omt = 1.0 - t;
for (unsigned c=0 ; c<chmap.m_channelCount ; ++c)
{
for (unsigned c = 0; c < chmap.m_channelCount; ++c) {
AudioChannel ch = chmap.m_channels[c];
if (ch != AudioChannel::Unknown)
{
*dataOut = Clamp16(*dataOut +
*dataIn * (m_coefs.v[int(ch)][0] * t + m_oldCoefs.v[int(ch)][0] * omt) +
if (ch != AudioChannel::Unknown) {
*dataOut = Clamp16(*dataOut + *dataIn * (m_coefs.v[int(ch)][0] * t + m_oldCoefs.v[int(ch)][0] * omt) +
*dataIn * (m_coefs.v[int(ch)][1] * t + m_oldCoefs.v[int(ch)][1] * omt));
++dataOut;
}
}
++m_curSlewFrame;
}
else
{
for (unsigned c=0 ; c<chmap.m_channelCount ; ++c)
{
} else {
for (unsigned c = 0; c < chmap.m_channelCount; ++c) {
AudioChannel ch = chmap.m_channels[c];
if (ch != AudioChannel::Unknown)
{
*dataOut = Clamp16(*dataOut +
dataIn[0] * m_coefs.v[int(ch)][0] +
dataIn[1] * m_coefs.v[int(ch)][1]);
if (ch != AudioChannel::Unknown) {
*dataOut = Clamp16(*dataOut + dataIn[0] * m_coefs.v[int(ch)][0] + dataIn[1] * m_coefs.v[int(ch)][1]);
++dataOut;
}
}
@ -206,41 +164,29 @@ int16_t* AudioMatrixStereo::mixStereoSampleData(const AudioVoiceEngineMixInfo& i
return dataOut;
}
int32_t* AudioMatrixStereo::mixStereoSampleData(const AudioVoiceEngineMixInfo& info,
const int32_t* dataIn, int32_t* dataOut, size_t frames)
{
int32_t* AudioMatrixStereo::mixStereoSampleData(const AudioVoiceEngineMixInfo& info, const int32_t* dataIn,
int32_t* dataOut, size_t frames) {
const ChannelMap& chmap = info.m_channelMap;
for (size_t f=0 ; f<frames ; ++f, dataIn += 2)
{
if (m_slewFrames && m_curSlewFrame < m_slewFrames)
{
for (size_t f = 0; f < frames; ++f, dataIn += 2) {
if (m_slewFrames && m_curSlewFrame < m_slewFrames) {
double t = m_curSlewFrame / double(m_slewFrames);
double omt = 1.0 - t;
for (unsigned c=0 ; c<chmap.m_channelCount ; ++c)
{
for (unsigned c = 0; c < chmap.m_channelCount; ++c) {
AudioChannel ch = chmap.m_channels[c];
if (ch != AudioChannel::Unknown)
{
*dataOut = Clamp32(*dataOut +
*dataIn * (m_coefs.v[int(ch)][0] * t + m_oldCoefs.v[int(ch)][0] * omt) +
if (ch != AudioChannel::Unknown) {
*dataOut = Clamp32(*dataOut + *dataIn * (m_coefs.v[int(ch)][0] * t + m_oldCoefs.v[int(ch)][0] * omt) +
*dataIn * (m_coefs.v[int(ch)][1] * t + m_oldCoefs.v[int(ch)][1] * omt));
++dataOut;
}
}
++m_curSlewFrame;
}
else
{
for (unsigned c=0 ; c<chmap.m_channelCount ; ++c)
{
} else {
for (unsigned c = 0; c < chmap.m_channelCount; ++c) {
AudioChannel ch = chmap.m_channels[c];
if (ch != AudioChannel::Unknown)
{
*dataOut = Clamp32(*dataOut +
dataIn[0] * m_coefs.v[int(ch)][0] +
dataIn[1] * m_coefs.v[int(ch)][1]);
if (ch != AudioChannel::Unknown) {
*dataOut = Clamp32(*dataOut + dataIn[0] * m_coefs.v[int(ch)][0] + dataIn[1] * m_coefs.v[int(ch)][1]);
++dataOut;
}
}
@ -249,41 +195,29 @@ int32_t* AudioMatrixStereo::mixStereoSampleData(const AudioVoiceEngineMixInfo& i
return dataOut;
}
float* AudioMatrixStereo::mixStereoSampleData(const AudioVoiceEngineMixInfo& info,
const float* dataIn, float* dataOut, size_t frames)
{
float* AudioMatrixStereo::mixStereoSampleData(const AudioVoiceEngineMixInfo& info, const float* dataIn, float* dataOut,
size_t frames) {
const ChannelMap& chmap = info.m_channelMap;
for (size_t f=0 ; f<frames ; ++f, dataIn += 2)
{
if (m_slewFrames && m_curSlewFrame < m_slewFrames)
{
for (size_t f = 0; f < frames; ++f, dataIn += 2) {
if (m_slewFrames && m_curSlewFrame < m_slewFrames) {
double t = m_curSlewFrame / double(m_slewFrames);
double omt = 1.0 - t;
for (unsigned c=0 ; c<chmap.m_channelCount ; ++c)
{
for (unsigned c = 0; c < chmap.m_channelCount; ++c) {
AudioChannel ch = chmap.m_channels[c];
if (ch != AudioChannel::Unknown)
{
*dataOut = *dataOut +
*dataIn * (m_coefs.v[int(ch)][0] * t + m_oldCoefs.v[int(ch)][0] * omt) +
if (ch != AudioChannel::Unknown) {
*dataOut = *dataOut + *dataIn * (m_coefs.v[int(ch)][0] * t + m_oldCoefs.v[int(ch)][0] * omt) +
*dataIn * (m_coefs.v[int(ch)][1] * t + m_oldCoefs.v[int(ch)][1] * omt);
++dataOut;
}
}
++m_curSlewFrame;
}
else
{
for (unsigned c=0 ; c<chmap.m_channelCount ; ++c)
{
} else {
for (unsigned c = 0; c < chmap.m_channelCount; ++c) {
AudioChannel ch = chmap.m_channels[c];
if (ch != AudioChannel::Unknown)
{
*dataOut = *dataOut +
dataIn[0] * m_coefs.v[int(ch)][0] +
dataIn[1] * m_coefs.v[int(ch)][1];
if (ch != AudioChannel::Unknown) {
*dataOut = *dataOut + dataIn[0] * m_coefs.v[int(ch)][0] + dataIn[1] * m_coefs.v[int(ch)][1];
++dataOut;
}
}
@ -292,5 +226,4 @@ float* AudioMatrixStereo::mixStereoSampleData(const AudioVoiceEngineMixInfo& inf
return dataOut;
}
}
} // namespace boo

View File

@ -10,12 +10,10 @@
#include <immintrin.h>
#endif
namespace boo
{
namespace boo {
struct AudioVoiceEngineMixInfo;
static inline int16_t Clamp16(float in)
{
static inline int16_t Clamp16(float in) {
if (in < SHRT_MIN)
return SHRT_MIN;
else if (in > SHRT_MAX)
@ -23,8 +21,7 @@ static inline int16_t Clamp16(float in)
return in;
}
static inline int32_t Clamp32(float in)
{
static inline int32_t Clamp32(float in) {
if (in < INT_MIN)
return INT_MIN;
else if (in > INT_MAX)
@ -32,10 +29,8 @@ static inline int32_t Clamp32(float in)
return in;
}
class AudioMatrixMono
{
union Coefs
{
class AudioMatrixMono {
union Coefs {
float v[8];
#if __SSE__
__m128 q[2];
@ -46,24 +41,22 @@ class AudioMatrixMono
Coefs m_oldCoefs = {};
size_t m_slewFrames = 0;
size_t m_curSlewFrame = ~size_t(0);
public:
AudioMatrixMono() { setDefaultMatrixCoefficients(AudioChannelSet::Stereo); }
void setDefaultMatrixCoefficients(AudioChannelSet acSet);
void setMatrixCoefficients(const float coefs[8], size_t slewFrames=0)
{
void setMatrixCoefficients(const float coefs[8], size_t slewFrames = 0) {
m_slewFrames = slewFrames;
#if __SSE__
if (m_curSlewFrame != 0)
{
if (m_curSlewFrame != 0) {
m_oldCoefs.q[0] = m_coefs.q[0];
m_oldCoefs.q[1] = m_coefs.q[1];
}
m_coefs.q[0] = _mm_loadu_ps(coefs);
m_coefs.q[1] = _mm_loadu_ps(&coefs[4]);
#else
for (int i=0 ; i<8 ; ++i)
{
for (int i = 0; i < 8; ++i) {
if (m_curSlewFrame != 0)
m_oldCoefs.v[i] = m_coefs.v[i];
m_coefs.v[i] = coefs[i];
@ -72,15 +65,13 @@ public:
m_curSlewFrame = 0;
}
int16_t* mixMonoSampleData(const AudioVoiceEngineMixInfo& info,
const int16_t* dataIn, int16_t* dataOut, size_t samples);
int32_t* mixMonoSampleData(const AudioVoiceEngineMixInfo& info,
const int32_t* dataIn, int32_t* dataOut, size_t samples);
float* mixMonoSampleData(const AudioVoiceEngineMixInfo& info,
const float* dataIn, float* dataOut, size_t samples);
int16_t* mixMonoSampleData(const AudioVoiceEngineMixInfo& info, const int16_t* dataIn, int16_t* dataOut,
size_t samples);
int32_t* mixMonoSampleData(const AudioVoiceEngineMixInfo& info, const int32_t* dataIn, int32_t* dataOut,
size_t samples);
float* mixMonoSampleData(const AudioVoiceEngineMixInfo& info, const float* dataIn, float* dataOut, size_t samples);
bool isSilent() const
{
bool isSilent() const {
if (m_curSlewFrame < m_slewFrames)
for (int i = 0; i < 8; ++i)
if (m_oldCoefs.v[i] > FLT_EPSILON)
@ -92,10 +83,8 @@ public:
}
};
class AudioMatrixStereo
{
union Coefs
{
class AudioMatrixStereo {
union Coefs {
float v[8][2];
#if __SSE__
__m128 q[4];
@ -106,16 +95,15 @@ class AudioMatrixStereo
Coefs m_oldCoefs = {};
size_t m_slewFrames = 0;
size_t m_curSlewFrame = ~size_t(0);
public:
AudioMatrixStereo() { setDefaultMatrixCoefficients(AudioChannelSet::Stereo); }
void setDefaultMatrixCoefficients(AudioChannelSet acSet);
void setMatrixCoefficients(const float coefs[8][2], size_t slewFrames=0)
{
void setMatrixCoefficients(const float coefs[8][2], size_t slewFrames = 0) {
m_slewFrames = slewFrames;
#if __SSE__
if (m_curSlewFrame != 0)
{
if (m_curSlewFrame != 0) {
m_oldCoefs.q[0] = m_coefs.q[0];
m_oldCoefs.q[1] = m_coefs.q[1];
m_oldCoefs.q[2] = m_coefs.q[2];
@ -126,10 +114,8 @@ public:
m_coefs.q[2] = _mm_loadu_ps(coefs[4]);
m_coefs.q[3] = _mm_loadu_ps(coefs[6]);
#else
for (int i=0 ; i<8 ; ++i)
{
if (m_curSlewFrame != 0)
{
for (int i = 0; i < 8; ++i) {
if (m_curSlewFrame != 0) {
m_oldCoefs.v[i][0] = m_coefs.v[i][0];
m_oldCoefs.v[i][1] = m_coefs.v[i][1];
}
@ -140,15 +126,13 @@ public:
m_curSlewFrame = 0;
}
int16_t* mixStereoSampleData(const AudioVoiceEngineMixInfo& info,
const int16_t* dataIn, int16_t* dataOut, size_t frames);
int32_t* mixStereoSampleData(const AudioVoiceEngineMixInfo& info,
const int32_t* dataIn, int32_t* dataOut, size_t frames);
float* mixStereoSampleData(const AudioVoiceEngineMixInfo& info,
const float* dataIn, float* dataOut, size_t frames);
int16_t* mixStereoSampleData(const AudioVoiceEngineMixInfo& info, const int16_t* dataIn, int16_t* dataOut,
size_t frames);
int32_t* mixStereoSampleData(const AudioVoiceEngineMixInfo& info, const int32_t* dataIn, int32_t* dataOut,
size_t frames);
float* mixStereoSampleData(const AudioVoiceEngineMixInfo& info, const float* dataIn, float* dataOut, size_t frames);
bool isSilent() const
{
bool isSilent() const {
if (m_curSlewFrame < m_slewFrames)
for (int i = 0; i < 8; ++i)
if (m_oldCoefs.v[i][0] > FLT_EPSILON || m_oldCoefs.v[i][1] > FLT_EPSILON)
@ -160,5 +144,4 @@ public:
}
};
}
} // namespace boo

View File

@ -4,11 +4,9 @@
#include <immintrin.h>
namespace boo
{
namespace boo {
typedef union
{
typedef union {
float v[4];
#if __SSE__
__m128 q;
@ -19,14 +17,12 @@ typedef union
static constexpr TVectorUnion Min32Vec = {{INT32_MIN, INT32_MIN, INT32_MIN, INT32_MIN}};
static constexpr TVectorUnion Max32Vec = {{INT32_MAX, INT32_MAX, INT32_MAX, INT32_MAX}};
void AudioMatrixMono::setDefaultMatrixCoefficients(AudioChannelSet acSet)
{
void AudioMatrixMono::setDefaultMatrixCoefficients(AudioChannelSet acSet) {
m_curSlewFrame = 0;
m_slewFrames = 0;
m_coefs.q[0] = _mm_xor_ps(m_coefs.q[0], m_coefs.q[0]);
m_coefs.q[1] = _mm_xor_ps(m_coefs.q[1], m_coefs.q[1]);
switch (acSet)
{
switch (acSet) {
case AudioChannelSet::Stereo:
case AudioChannelSet::Quad:
m_coefs.v[int(AudioChannel::FrontLeft)] = 1.0;
@ -36,40 +32,32 @@ void AudioMatrixMono::setDefaultMatrixCoefficients(AudioChannelSet acSet)
case AudioChannelSet::Surround71:
m_coefs.v[int(AudioChannel::FrontCenter)] = 1.0;
break;
default: break;
default:
break;
}
}
int16_t* AudioMatrixMono::mixMonoSampleData(const AudioVoiceEngineMixInfo& info,
const int16_t* dataIn, int16_t* dataOut, size_t samples)
{
int16_t* AudioMatrixMono::mixMonoSampleData(const AudioVoiceEngineMixInfo& info, const int16_t* dataIn,
int16_t* dataOut, size_t samples) {
const ChannelMap& chmap = info.m_channelMap;
for (size_t s=0 ; s<samples ; ++s, ++dataIn)
{
if (m_slewFrames && m_curSlewFrame < m_slewFrames)
{
for (size_t s = 0; s < samples; ++s, ++dataIn) {
if (m_slewFrames && m_curSlewFrame < m_slewFrames) {
double t = m_curSlewFrame / double(m_slewFrames);
double omt = 1.0 - t;
for (unsigned c=0 ; c<chmap.m_channelCount ; ++c)
{
for (unsigned c = 0; c < chmap.m_channelCount; ++c) {
AudioChannel ch = chmap.m_channels[c];
if (ch != AudioChannel::Unknown)
{
if (ch != AudioChannel::Unknown) {
*dataOut = Clamp16(*dataOut + *dataIn * (m_coefs.v[int(ch)] * t + m_oldCoefs.v[int(ch)] * omt));
++dataOut;
}
}
++m_curSlewFrame;
}
else
{
for (unsigned c=0 ; c<chmap.m_channelCount ; ++c)
{
} else {
for (unsigned c = 0; c < chmap.m_channelCount; ++c) {
AudioChannel ch = chmap.m_channels[c];
if (ch != AudioChannel::Unknown)
{
if (ch != AudioChannel::Unknown) {
*dataOut = Clamp16(*dataOut + *dataIn * m_coefs.v[int(ch)]);
++dataOut;
}
@ -79,28 +67,23 @@ int16_t* AudioMatrixMono::mixMonoSampleData(const AudioVoiceEngineMixInfo& info,
return dataOut;
}
int32_t* AudioMatrixMono::mixMonoSampleData(const AudioVoiceEngineMixInfo& info,
const int32_t* dataIn, int32_t* dataOut, size_t samples)
{
int32_t* AudioMatrixMono::mixMonoSampleData(const AudioVoiceEngineMixInfo& info, const int32_t* dataIn,
int32_t* dataOut, size_t samples) {
const ChannelMap& chmap = info.m_channelMap;
for (size_t s=0 ; s<samples ; ++s, ++dataIn)
{
if (m_slewFrames && m_curSlewFrame < m_slewFrames)
{
for (size_t s = 0; s < samples; ++s, ++dataIn) {
if (m_slewFrames && m_curSlewFrame < m_slewFrames) {
float t = m_curSlewFrame / float(m_slewFrames);
float omt = 1.f - t;
switch (chmap.m_channelCount)
{
case 2:
{
switch (chmap.m_channelCount) {
case 2: {
++m_curSlewFrame;
float t2 = m_curSlewFrame / float(m_slewFrames);
float omt2 = 1.f - t2;
TVectorUnion coefs, samps;
coefs.q = _mm_add_ps(_mm_mul_ps(_mm_shuffle_ps(m_coefs.q[0], m_coefs.q[0], _MM_SHUFFLE(1, 0, 1, 0)),
_mm_set_ps(t, t, t2, t2)),
coefs.q = _mm_add_ps(
_mm_mul_ps(_mm_shuffle_ps(m_coefs.q[0], m_coefs.q[0], _MM_SHUFFLE(1, 0, 1, 0)), _mm_set_ps(t, t, t2, t2)),
_mm_mul_ps(_mm_shuffle_ps(m_oldCoefs.q[0], m_oldCoefs.q[0], _MM_SHUFFLE(1, 0, 1, 0)),
_mm_set_ps(omt, omt, omt2, omt2)));
samps.q = _mm_cvtepi32_ps(_mm_set_epi32(dataIn[1], dataIn[0], dataIn[1], dataIn[0]));
@ -114,11 +97,9 @@ int32_t* AudioMatrixMono::mixMonoSampleData(const AudioVoiceEngineMixInfo& info,
++dataIn;
break;
}
case 4:
{
case 4: {
TVectorUnion coefs, samps;
coefs.q = _mm_add_ps(_mm_mul_ps(m_coefs.q[0], _mm_set1_ps(t)),
_mm_mul_ps(m_oldCoefs.q[0], _mm_set1_ps(omt)));
coefs.q = _mm_add_ps(_mm_mul_ps(m_coefs.q[0], _mm_set1_ps(t)), _mm_mul_ps(m_oldCoefs.q[0], _mm_set1_ps(omt)));
samps.q = _mm_cvtepi32_ps(_mm_loadu_si128(reinterpret_cast<const __m128i*>(dataIn)));
__m128i* out = reinterpret_cast<__m128i*>(dataOut);
@ -128,11 +109,9 @@ int32_t* AudioMatrixMono::mixMonoSampleData(const AudioVoiceEngineMixInfo& info,
dataOut += 4;
break;
}
case 6:
{
case 6: {
TVectorUnion coefs, samps;
coefs.q = _mm_add_ps(_mm_mul_ps(m_coefs.q[0], _mm_set1_ps(t)),
_mm_mul_ps(m_oldCoefs.q[0], _mm_set1_ps(omt)));
coefs.q = _mm_add_ps(_mm_mul_ps(m_coefs.q[0], _mm_set1_ps(t)), _mm_mul_ps(m_oldCoefs.q[0], _mm_set1_ps(omt)));
samps.q = _mm_cvtepi32_ps(_mm_loadu_si128(reinterpret_cast<const __m128i*>(dataIn)));
__m128i* out = reinterpret_cast<__m128i*>(dataOut);
@ -141,8 +120,7 @@ int32_t* AudioMatrixMono::mixMonoSampleData(const AudioVoiceEngineMixInfo& info,
dataOut += 4;
coefs.q = _mm_add_ps(_mm_mul_ps(m_coefs.q[1], _mm_set1_ps(t)),
_mm_mul_ps(m_oldCoefs.q[1], _mm_set1_ps(omt)));
coefs.q = _mm_add_ps(_mm_mul_ps(m_coefs.q[1], _mm_set1_ps(t)), _mm_mul_ps(m_oldCoefs.q[1], _mm_set1_ps(omt)));
samps.q = _mm_cvtepi32_ps(_mm_loadu_si128(reinterpret_cast<const __m128i*>(dataIn)));
out = reinterpret_cast<__m128i*>(dataOut);
@ -153,11 +131,9 @@ int32_t* AudioMatrixMono::mixMonoSampleData(const AudioVoiceEngineMixInfo& info,
dataOut += 2;
break;
}
case 8:
{
case 8: {
TVectorUnion coefs, samps;
coefs.q = _mm_add_ps(_mm_mul_ps(m_coefs.q[0], _mm_set1_ps(t)),
_mm_mul_ps(m_oldCoefs.q[0], _mm_set1_ps(omt)));
coefs.q = _mm_add_ps(_mm_mul_ps(m_coefs.q[0], _mm_set1_ps(t)), _mm_mul_ps(m_oldCoefs.q[0], _mm_set1_ps(omt)));
samps.q = _mm_cvtepi32_ps(_mm_loadu_si128(reinterpret_cast<const __m128i*>(dataIn)));
__m128i* out = reinterpret_cast<__m128i*>(dataOut);
@ -166,8 +142,7 @@ int32_t* AudioMatrixMono::mixMonoSampleData(const AudioVoiceEngineMixInfo& info,
dataOut += 4;
coefs.q = _mm_add_ps(_mm_mul_ps(m_coefs.q[1], _mm_set1_ps(t)),
_mm_mul_ps(m_oldCoefs.q[1], _mm_set1_ps(omt)));
coefs.q = _mm_add_ps(_mm_mul_ps(m_coefs.q[1], _mm_set1_ps(t)), _mm_mul_ps(m_oldCoefs.q[1], _mm_set1_ps(omt)));
samps.q = _mm_cvtepi32_ps(_mm_loadu_si128(reinterpret_cast<const __m128i*>(dataIn)));
out = reinterpret_cast<__m128i*>(dataOut);
@ -177,13 +152,10 @@ int32_t* AudioMatrixMono::mixMonoSampleData(const AudioVoiceEngineMixInfo& info,
dataOut += 4;
break;
}
default:
{
for (unsigned c=0 ; c<chmap.m_channelCount ; ++c)
{
default: {
for (unsigned c = 0; c < chmap.m_channelCount; ++c) {
AudioChannel ch = chmap.m_channels[c];
if (ch != AudioChannel::Unknown)
{
if (ch != AudioChannel::Unknown) {
*dataOut = Clamp32(*dataOut + *dataIn * (m_coefs.v[int(ch)] * t + m_oldCoefs.v[int(ch)] * omt));
++dataOut;
}
@ -193,13 +165,9 @@ int32_t* AudioMatrixMono::mixMonoSampleData(const AudioVoiceEngineMixInfo& info,
}
++m_curSlewFrame;
}
else
{
switch (chmap.m_channelCount)
{
case 2:
{
} else {
switch (chmap.m_channelCount) {
case 2: {
TVectorUnion coefs, samps;
coefs.q = _mm_shuffle_ps(m_coefs.q[0], m_coefs.q[0], _MM_SHUFFLE(1, 0, 1, 0));
samps.q = _mm_cvtepi32_ps(_mm_set_epi32(dataIn[1], dataIn[0], dataIn[1], dataIn[0]));
@ -215,8 +183,7 @@ int32_t* AudioMatrixMono::mixMonoSampleData(const AudioVoiceEngineMixInfo& info,
++dataIn;
break;
}
case 4:
{
case 4: {
TVectorUnion samps;
samps.q = _mm_cvtepi32_ps(_mm_loadu_si128(reinterpret_cast<const __m128i*>(dataIn)));
@ -227,8 +194,7 @@ int32_t* AudioMatrixMono::mixMonoSampleData(const AudioVoiceEngineMixInfo& info,
dataOut += 4;
break;
}
case 6:
{
case 6: {
TVectorUnion samps;
samps.q = _mm_cvtepi32_ps(_mm_loadu_si128(reinterpret_cast<const __m128i*>(dataIn)));
@ -248,8 +214,7 @@ int32_t* AudioMatrixMono::mixMonoSampleData(const AudioVoiceEngineMixInfo& info,
dataOut += 2;
break;
}
case 8:
{
case 8: {
TVectorUnion samps;
samps.q = _mm_cvtepi32_ps(_mm_loadu_si128(reinterpret_cast<const __m128i*>(dataIn)));
@ -268,13 +233,10 @@ int32_t* AudioMatrixMono::mixMonoSampleData(const AudioVoiceEngineMixInfo& info,
dataOut += 4;
break;
}
default:
{
for (unsigned c=0 ; c<chmap.m_channelCount ; ++c)
{
default: {
for (unsigned c = 0; c < chmap.m_channelCount; ++c) {
AudioChannel ch = chmap.m_channels[c];
if (ch != AudioChannel::Unknown)
{
if (ch != AudioChannel::Unknown) {
*dataOut = Clamp32(*dataOut + *dataIn * m_coefs.v[int(ch)]);
++dataOut;
}
@ -287,28 +249,23 @@ int32_t* AudioMatrixMono::mixMonoSampleData(const AudioVoiceEngineMixInfo& info,
return dataOut;
}
float* AudioMatrixMono::mixMonoSampleData(const AudioVoiceEngineMixInfo& info,
const float* dataIn, float* dataOut, size_t samples)
{
float* AudioMatrixMono::mixMonoSampleData(const AudioVoiceEngineMixInfo& info, const float* dataIn, float* dataOut,
size_t samples) {
const ChannelMap& chmap = info.m_channelMap;
for (size_t s=0 ; s<samples ; ++s, ++dataIn)
{
if (m_slewFrames && m_curSlewFrame < m_slewFrames)
{
for (size_t s = 0; s < samples; ++s, ++dataIn) {
if (m_slewFrames && m_curSlewFrame < m_slewFrames) {
float t = m_curSlewFrame / float(m_slewFrames);
float omt = 1.f - t;
switch (chmap.m_channelCount)
{
case 2:
{
switch (chmap.m_channelCount) {
case 2: {
++m_curSlewFrame;
float t2 = m_curSlewFrame / float(m_slewFrames);
float omt2 = 1.f - t2;
TVectorUnion coefs, samps;
coefs.q = _mm_add_ps(_mm_mul_ps(_mm_shuffle_ps(m_coefs.q[0], m_coefs.q[0], _MM_SHUFFLE(1, 0, 1, 0)),
_mm_set_ps(t, t, t2, t2)),
coefs.q = _mm_add_ps(
_mm_mul_ps(_mm_shuffle_ps(m_coefs.q[0], m_coefs.q[0], _MM_SHUFFLE(1, 0, 1, 0)), _mm_set_ps(t, t, t2, t2)),
_mm_mul_ps(_mm_shuffle_ps(m_oldCoefs.q[0], m_oldCoefs.q[0], _MM_SHUFFLE(1, 0, 1, 0)),
_mm_set_ps(omt, omt, omt2, omt2)));
samps.q = _mm_loadu_ps(dataIn);
@ -322,13 +279,10 @@ float* AudioMatrixMono::mixMonoSampleData(const AudioVoiceEngineMixInfo& info,
++dataIn;
break;
}
default:
{
for (unsigned c=0 ; c<chmap.m_channelCount ; ++c)
{
default: {
for (unsigned c = 0; c < chmap.m_channelCount; ++c) {
AudioChannel ch = chmap.m_channels[c];
if (ch != AudioChannel::Unknown)
{
if (ch != AudioChannel::Unknown) {
*dataOut = *dataOut + *dataIn * (m_coefs.v[int(ch)] * t + m_oldCoefs.v[int(ch)] * omt);
++dataOut;
}
@ -338,13 +292,9 @@ float* AudioMatrixMono::mixMonoSampleData(const AudioVoiceEngineMixInfo& info,
}
++m_curSlewFrame;
}
else
{
switch (chmap.m_channelCount)
{
case 2:
{
} else {
switch (chmap.m_channelCount) {
case 2: {
TVectorUnion coefs, samps;
coefs.q = _mm_shuffle_ps(m_coefs.q[0], m_coefs.q[0], _MM_SHUFFLE(1, 0, 1, 0));
samps.q = _mm_loadu_ps(dataIn);
@ -358,13 +308,10 @@ float* AudioMatrixMono::mixMonoSampleData(const AudioVoiceEngineMixInfo& info,
++dataIn;
break;
}
default:
{
for (unsigned c=0 ; c<chmap.m_channelCount ; ++c)
{
default: {
for (unsigned c = 0; c < chmap.m_channelCount; ++c) {
AudioChannel ch = chmap.m_channels[c];
if (ch != AudioChannel::Unknown)
{
if (ch != AudioChannel::Unknown) {
*dataOut = *dataOut + *dataIn * m_coefs.v[int(ch)];
++dataOut;
}
@ -377,16 +324,14 @@ float* AudioMatrixMono::mixMonoSampleData(const AudioVoiceEngineMixInfo& info,
return dataOut;
}
void AudioMatrixStereo::setDefaultMatrixCoefficients(AudioChannelSet acSet)
{
void AudioMatrixStereo::setDefaultMatrixCoefficients(AudioChannelSet acSet) {
m_curSlewFrame = 0;
m_slewFrames = 0;
m_coefs.q[0] = _mm_xor_ps(m_coefs.q[0], m_coefs.q[0]);
m_coefs.q[1] = _mm_xor_ps(m_coefs.q[1], m_coefs.q[1]);
m_coefs.q[2] = _mm_xor_ps(m_coefs.q[2], m_coefs.q[2]);
m_coefs.q[3] = _mm_xor_ps(m_coefs.q[3], m_coefs.q[3]);
switch (acSet)
{
switch (acSet) {
case AudioChannelSet::Stereo:
case AudioChannelSet::Quad:
m_coefs.v[int(AudioChannel::FrontLeft)][0] = 1.0;
@ -397,45 +342,34 @@ void AudioMatrixStereo::setDefaultMatrixCoefficients(AudioChannelSet acSet)
m_coefs.v[int(AudioChannel::FrontLeft)][0] = 1.0;
m_coefs.v[int(AudioChannel::FrontRight)][1] = 1.0;
break;
default: break;
default:
break;
}
}
int16_t* AudioMatrixStereo::mixStereoSampleData(const AudioVoiceEngineMixInfo& info,
const int16_t* dataIn, int16_t* dataOut, size_t frames)
{
int16_t* AudioMatrixStereo::mixStereoSampleData(const AudioVoiceEngineMixInfo& info, const int16_t* dataIn,
int16_t* dataOut, size_t frames) {
const ChannelMap& chmap = info.m_channelMap;
for (size_t f=0 ; f<frames ; ++f, dataIn += 2)
{
if (m_slewFrames && m_curSlewFrame < m_slewFrames)
{
for (size_t f = 0; f < frames; ++f, dataIn += 2) {
if (m_slewFrames && m_curSlewFrame < m_slewFrames) {
double t = m_curSlewFrame / double(m_slewFrames);
double omt = 1.0 - t;
for (unsigned c=0 ; c<chmap.m_channelCount ; ++c)
{
for (unsigned c = 0; c < chmap.m_channelCount; ++c) {
AudioChannel ch = chmap.m_channels[c];
if (ch != AudioChannel::Unknown)
{
*dataOut = Clamp16(*dataOut +
*dataIn * (m_coefs.v[int(ch)][0] * t + m_oldCoefs.v[int(ch)][0] * omt) +
if (ch != AudioChannel::Unknown) {
*dataOut = Clamp16(*dataOut + *dataIn * (m_coefs.v[int(ch)][0] * t + m_oldCoefs.v[int(ch)][0] * omt) +
*dataIn * (m_coefs.v[int(ch)][1] * t + m_oldCoefs.v[int(ch)][1] * omt));
++dataOut;
}
}
++m_curSlewFrame;
}
else
{
for (unsigned c=0 ; c<chmap.m_channelCount ; ++c)
{
} else {
for (unsigned c = 0; c < chmap.m_channelCount; ++c) {
AudioChannel ch = chmap.m_channels[c];
if (ch != AudioChannel::Unknown)
{
*dataOut = Clamp16(*dataOut +
dataIn[0] * m_coefs.v[int(ch)][0] +
dataIn[1] * m_coefs.v[int(ch)][1]);
if (ch != AudioChannel::Unknown) {
*dataOut = Clamp16(*dataOut + dataIn[0] * m_coefs.v[int(ch)][0] + dataIn[1] * m_coefs.v[int(ch)][1]);
++dataOut;
}
}
@ -444,41 +378,29 @@ int16_t* AudioMatrixStereo::mixStereoSampleData(const AudioVoiceEngineMixInfo& i
return dataOut;
}
int32_t* AudioMatrixStereo::mixStereoSampleData(const AudioVoiceEngineMixInfo& info,
const int32_t* dataIn, int32_t* dataOut, size_t frames)
{
int32_t* AudioMatrixStereo::mixStereoSampleData(const AudioVoiceEngineMixInfo& info, const int32_t* dataIn,
int32_t* dataOut, size_t frames) {
const ChannelMap& chmap = info.m_channelMap;
for (size_t f=0 ; f<frames ; ++f, dataIn += 2)
{
if (m_slewFrames && m_curSlewFrame < m_slewFrames)
{
for (size_t f = 0; f < frames; ++f, dataIn += 2) {
if (m_slewFrames && m_curSlewFrame < m_slewFrames) {
double t = m_curSlewFrame / double(m_slewFrames);
double omt = 1.0 - t;
for (unsigned c=0 ; c<chmap.m_channelCount ; ++c)
{
for (unsigned c = 0; c < chmap.m_channelCount; ++c) {
AudioChannel ch = chmap.m_channels[c];
if (ch != AudioChannel::Unknown)
{
*dataOut = Clamp32(*dataOut +
*dataIn * (m_coefs.v[int(ch)][0] * t + m_oldCoefs.v[int(ch)][0] * omt) +
if (ch != AudioChannel::Unknown) {
*dataOut = Clamp32(*dataOut + *dataIn * (m_coefs.v[int(ch)][0] * t + m_oldCoefs.v[int(ch)][0] * omt) +
*dataIn * (m_coefs.v[int(ch)][1] * t + m_oldCoefs.v[int(ch)][1] * omt));
++dataOut;
}
}
++m_curSlewFrame;
}
else
{
for (unsigned c=0 ; c<chmap.m_channelCount ; ++c)
{
} else {
for (unsigned c = 0; c < chmap.m_channelCount; ++c) {
AudioChannel ch = chmap.m_channels[c];
if (ch != AudioChannel::Unknown)
{
*dataOut = Clamp32(*dataOut +
dataIn[0] * m_coefs.v[int(ch)][0] +
dataIn[1] * m_coefs.v[int(ch)][1]);
if (ch != AudioChannel::Unknown) {
*dataOut = Clamp32(*dataOut + dataIn[0] * m_coefs.v[int(ch)][0] + dataIn[1] * m_coefs.v[int(ch)][1]);
++dataOut;
}
}
@ -487,41 +409,29 @@ int32_t* AudioMatrixStereo::mixStereoSampleData(const AudioVoiceEngineMixInfo& i
return dataOut;
}
float* AudioMatrixStereo::mixStereoSampleData(const AudioVoiceEngineMixInfo& info,
const float* dataIn, float* dataOut, size_t frames)
{
float* AudioMatrixStereo::mixStereoSampleData(const AudioVoiceEngineMixInfo& info, const float* dataIn, float* dataOut,
size_t frames) {
const ChannelMap& chmap = info.m_channelMap;
for (size_t f=0 ; f<frames ; ++f, dataIn += 2)
{
if (m_slewFrames && m_curSlewFrame < m_slewFrames)
{
for (size_t f = 0; f < frames; ++f, dataIn += 2) {
if (m_slewFrames && m_curSlewFrame < m_slewFrames) {
double t = m_curSlewFrame / double(m_slewFrames);
double omt = 1.0 - t;
for (unsigned c=0 ; c<chmap.m_channelCount ; ++c)
{
for (unsigned c = 0; c < chmap.m_channelCount; ++c) {
AudioChannel ch = chmap.m_channels[c];
if (ch != AudioChannel::Unknown)
{
*dataOut = *dataOut +
*dataIn * (m_coefs.v[int(ch)][0] * t + m_oldCoefs.v[int(ch)][0] * omt) +
if (ch != AudioChannel::Unknown) {
*dataOut = *dataOut + *dataIn * (m_coefs.v[int(ch)][0] * t + m_oldCoefs.v[int(ch)][0] * omt) +
*dataIn * (m_coefs.v[int(ch)][1] * t + m_oldCoefs.v[int(ch)][1] * omt);
++dataOut;
}
}
++m_curSlewFrame;
}
else
{
for (unsigned c=0 ; c<chmap.m_channelCount ; ++c)
{
} else {
for (unsigned c = 0; c < chmap.m_channelCount; ++c) {
AudioChannel ch = chmap.m_channels[c];
if (ch != AudioChannel::Unknown)
{
*dataOut = *dataOut +
dataIn[0] * m_coefs.v[int(ch)][0] +
dataIn[1] * m_coefs.v[int(ch)][1];
if (ch != AudioChannel::Unknown) {
*dataOut = *dataOut + dataIn[0] * m_coefs.v[int(ch)][0] + dataIn[1] * m_coefs.v[int(ch)][1];
++dataOut;
}
}
@ -530,5 +440,4 @@ float* AudioMatrixStereo::mixStereoSampleData(const AudioVoiceEngineMixInfo& inf
return dataOut;
}
}
} // namespace boo

View File

@ -7,53 +7,41 @@
#undef min
#undef max
namespace boo
{
namespace boo {
AudioSubmix::AudioSubmix(BaseAudioVoiceEngine& root, IAudioSubmixCallback* cb, int busId, bool mainOut)
: ListNode<AudioSubmix, BaseAudioVoiceEngine*, IAudioSubmix>(&root), m_busId(busId), m_mainOut(mainOut), m_cb(cb)
{
: ListNode<AudioSubmix, BaseAudioVoiceEngine*, IAudioSubmix>(&root), m_busId(busId), m_mainOut(mainOut), m_cb(cb) {
if (mainOut)
setSendLevel(m_head->m_mainSubmix.get(), 1.f, false);
}
AudioSubmix::~AudioSubmix()
{
m_head->m_submixesDirty = true;
}
AudioSubmix::~AudioSubmix() { m_head->m_submixesDirty = true; }
AudioSubmix*& AudioSubmix::_getHeadPtr(BaseAudioVoiceEngine* head) { return head->m_submixHead; }
std::unique_lock<std::recursive_mutex> AudioSubmix::_getHeadLock(BaseAudioVoiceEngine* head)
{ return std::unique_lock<std::recursive_mutex>{head->m_dataMutex}; }
std::unique_lock<std::recursive_mutex> AudioSubmix::destructorLock()
{ return std::unique_lock<std::recursive_mutex>{m_head->m_dataMutex}; }
bool AudioSubmix::_isDirectDependencyOf(AudioSubmix* send)
{
return m_sendGains.find(send) != m_sendGains.cend();
std::unique_lock<std::recursive_mutex> AudioSubmix::_getHeadLock(BaseAudioVoiceEngine* head) {
return std::unique_lock<std::recursive_mutex>{head->m_dataMutex};
}
std::unique_lock<std::recursive_mutex> AudioSubmix::destructorLock() {
return std::unique_lock<std::recursive_mutex>{m_head->m_dataMutex};
}
bool AudioSubmix::_mergeC3(std::list<AudioSubmix*>& output,
std::vector<std::list<AudioSubmix*>>& lists)
{
for (auto outerIt = lists.begin() ; outerIt != lists.cend() ; ++outerIt)
{
bool AudioSubmix::_isDirectDependencyOf(AudioSubmix* send) { return m_sendGains.find(send) != m_sendGains.cend(); }
bool AudioSubmix::_mergeC3(std::list<AudioSubmix*>& output, std::vector<std::list<AudioSubmix*>>& lists) {
for (auto outerIt = lists.begin(); outerIt != lists.cend(); ++outerIt) {
if (outerIt->empty())
continue;
AudioSubmix* smx = outerIt->front();
bool found = false;
for (auto innerIt = lists.begin() ; innerIt != lists.cend() ; ++innerIt)
{
for (auto innerIt = lists.begin(); innerIt != lists.cend(); ++innerIt) {
if (innerIt->empty() || outerIt == innerIt)
continue;
if (smx == innerIt->front())
{
if (smx == innerIt->front()) {
innerIt->pop_front();
found = true;
}
}
if (found)
{
if (found) {
outerIt->pop_front();
output.push_back(smx);
return true;
@ -62,12 +50,10 @@ bool AudioSubmix::_mergeC3(std::list<AudioSubmix*>& output,
return false;
}
std::list<AudioSubmix*> AudioSubmix::_linearizeC3()
{
std::list<AudioSubmix*> AudioSubmix::_linearizeC3() {
std::vector<std::list<AudioSubmix*>> lists = {{}};
if (m_head->m_submixHead)
for (AudioSubmix& smx : *m_head->m_submixHead)
{
for (AudioSubmix& smx : *m_head->m_submixHead) {
if (&smx == this)
continue;
if (smx._isDirectDependencyOf(this))
@ -83,8 +69,7 @@ std::list<AudioSubmix*> AudioSubmix::_linearizeC3()
}
template <typename T>
void AudioSubmix::_zeroFill()
{
void AudioSubmix::_zeroFill() {
if (_getScratch<T>().size())
std::fill(_getScratch<T>().begin(), _getScratch<T>().end(), 0);
}
@ -94,8 +79,7 @@ template void AudioSubmix::_zeroFill<int32_t>();
template void AudioSubmix::_zeroFill<float>();
template <typename T>
T* AudioSubmix::_getMergeBuf(size_t frames)
{
T* AudioSubmix::_getMergeBuf(size_t frames) {
if (_getRedirect<T>())
return _getRedirect<T>();
@ -111,14 +95,10 @@ template int32_t* AudioSubmix::_getMergeBuf<int32_t>(size_t frames);
template float* AudioSubmix::_getMergeBuf<float>(size_t frames);
template <typename T>
static inline T ClampInt(float in)
{
if (std::is_floating_point<T>())
{
static inline T ClampInt(float in) {
if (std::is_floating_point<T>()) {
return in; // Allow subsequent mixing stages to work with over-saturated values
}
else
{
} else {
constexpr T MAX = std::numeric_limits<T>::max();
constexpr T MIN = std::numeric_limits<T>::min();
@ -132,19 +112,15 @@ static inline T ClampInt(float in)
}
template <typename T>
size_t AudioSubmix::_pumpAndMix(size_t frames)
{
size_t AudioSubmix::_pumpAndMix(size_t frames) {
const ChannelMap& chMap = m_head->clientMixInfo().m_channelMap;
size_t chanCount = chMap.m_channelCount;
if (_getRedirect<T>())
{
if (_getRedirect<T>()) {
if (m_cb && m_cb->canApplyEffect())
m_cb->applyEffect(_getRedirect<T>(), frames, chMap, m_head->mixInfo().m_sampleRate);
_getRedirect<T>() += chanCount * frames;
}
else
{
} else {
size_t sampleCount = frames * chanCount;
if (_getScratch<T>().size() < sampleCount)
_getScratch<T>().resize(sampleCount);
@ -152,33 +128,26 @@ size_t AudioSubmix::_pumpAndMix(size_t frames)
m_cb->applyEffect(_getScratch<T>().data(), frames, chMap, m_head->mixInfo().m_sampleRate);
size_t curSlewFrame = m_slewFrames;
for (auto& smx : m_sendGains)
{
for (auto& smx : m_sendGains) {
curSlewFrame = m_curSlewFrame;
AudioSubmix& sm = *reinterpret_cast<AudioSubmix*>(smx.first);
auto it = _getScratch<T>().begin();
T* dataOut = sm._getMergeBuf<T>(frames);
for (size_t f=0 ; f<frames ; ++f)
{
if (m_slewFrames && curSlewFrame < m_slewFrames)
{
for (size_t f = 0; f < frames; ++f) {
if (m_slewFrames && curSlewFrame < m_slewFrames) {
double t = curSlewFrame / double(m_slewFrames);
double omt = 1.0 - t;
for (unsigned c=0 ; c<chanCount ; ++c)
{
for (unsigned c = 0; c < chanCount; ++c) {
*dataOut = ClampInt<T>(*dataOut + *it * (smx.second[1] * t + smx.second[0] * omt));
++it;
++dataOut;
}
++curSlewFrame;
}
else
{
for (unsigned c=0 ; c<chanCount ; ++c)
{
} else {
for (unsigned c = 0; c < chanCount; ++c) {
*dataOut = ClampInt<T>(*dataOut + *it * smx.second[1]);
++it;
++dataOut;
@ -196,25 +165,21 @@ template size_t AudioSubmix::_pumpAndMix<int16_t>(size_t frames);
template size_t AudioSubmix::_pumpAndMix<int32_t>(size_t frames);
template size_t AudioSubmix::_pumpAndMix<float>(size_t frames);
void AudioSubmix::_resetOutputSampleRate()
{
void AudioSubmix::_resetOutputSampleRate() {
if (m_cb)
m_cb->resetOutputSampleRate(m_head->mixInfo().m_sampleRate);
}
void AudioSubmix::resetSendLevels()
{
void AudioSubmix::resetSendLevels() {
if (m_sendGains.empty())
return;
m_sendGains.clear();
m_head->m_submixesDirty = true;
}
void AudioSubmix::setSendLevel(IAudioSubmix* submix, float level, bool slew)
{
void AudioSubmix::setSendLevel(IAudioSubmix* submix, float level, bool slew) {
auto search = m_sendGains.find(submix);
if (search == m_sendGains.cend())
{
if (search == m_sendGains.cend()) {
search = m_sendGains.emplace(submix, std::array<float, 2>{1.f, 1.f}).first;
m_head->m_submixesDirty = true;
}
@ -226,20 +191,12 @@ void AudioSubmix::setSendLevel(IAudioSubmix* submix, float level, bool slew)
search->second[1] = level;
}
const AudioVoiceEngineMixInfo& AudioSubmix::mixInfo() const
{
return m_head->mixInfo();
}
const AudioVoiceEngineMixInfo& AudioSubmix::mixInfo() const { return m_head->mixInfo(); }
double AudioSubmix::getSampleRate() const
{
return mixInfo().m_sampleRate;
}
double AudioSubmix::getSampleRate() const { return mixInfo().m_sampleRate; }
SubmixFormat AudioSubmix::getSampleFormat() const
{
switch (mixInfo().m_sampleFormat)
{
SubmixFormat AudioSubmix::getSampleFormat() const {
switch (mixInfo().m_sampleFormat) {
case SOXR_INT16_I:
default:
return SubmixFormat::Int16;
@ -250,4 +207,4 @@ SubmixFormat AudioSubmix::getSampleFormat() const
}
}
}
} // namespace boo

View File

@ -15,15 +15,13 @@ struct AudioUnitVoiceEngine;
struct VSTVoiceEngine;
struct WAVOutVoiceEngine;
namespace boo
{
namespace boo {
class BaseAudioVoiceEngine;
class AudioVoice;
struct AudioVoiceEngineMixInfo;
/* Output gains for each mix-send/channel */
class AudioSubmix : public ListNode<AudioSubmix, BaseAudioVoiceEngine*, IAudioSubmix>
{
class AudioSubmix : public ListNode<AudioSubmix, BaseAudioVoiceEngine*, IAudioSubmix> {
friend class BaseAudioVoiceEngine;
friend class AudioVoiceMono;
friend class AudioVoiceStereo;
@ -50,28 +48,32 @@ class AudioSubmix : public ListNode<AudioSubmix, BaseAudioVoiceEngine*, IAudioSu
std::vector<int16_t> m_scratch16;
std::vector<int32_t> m_scratch32;
std::vector<float> m_scratchFlt;
template <typename T> std::vector<T>& _getScratch();
template <typename T>
std::vector<T>& _getScratch();
/* Override scratch buffers with alternate destination */
int16_t* m_redirect16 = nullptr;
int32_t* m_redirect32 = nullptr;
float* m_redirectFlt = nullptr;
template <typename T> T*& _getRedirect();
template <typename T>
T*& _getRedirect();
/* C3-linearization support (to mitigate a potential diamond problem on 'clever' submix routes) */
bool _isDirectDependencyOf(AudioSubmix* send);
std::list<AudioSubmix*> _linearizeC3();
static bool _mergeC3(std::list<AudioSubmix*>& output,
std::vector<std::list<AudioSubmix*>>& lists);
static bool _mergeC3(std::list<AudioSubmix*>& output, std::vector<std::list<AudioSubmix*>>& lists);
/* Fill scratch buffers with silence for new mix cycle */
template <typename T> void _zeroFill();
template <typename T>
void _zeroFill();
/* Receive audio from a single voice / submix */
template <typename T> T* _getMergeBuf(size_t frames);
template <typename T>
T* _getMergeBuf(size_t frames);
/* Mix scratch buffers into sends */
template <typename T> size_t _pumpAndMix(size_t frames);
template <typename T>
size_t _pumpAndMix(size_t frames);
void _resetOutputSampleRate();
@ -90,13 +92,30 @@ public:
SubmixFormat getSampleFormat() const;
};
template <> inline std::vector<int16_t>& AudioSubmix::_getScratch() { return m_scratch16; }
template <> inline std::vector<int32_t>& AudioSubmix::_getScratch() { return m_scratch32; }
template <> inline std::vector<float>& AudioSubmix::_getScratch() { return m_scratchFlt; }
template <> inline int16_t*& AudioSubmix::_getRedirect<int16_t>() { return m_redirect16; }
template <> inline int32_t*& AudioSubmix::_getRedirect<int32_t>() { return m_redirect32; }
template <> inline float*& AudioSubmix::_getRedirect<float>() { return m_redirectFlt; }
template <>
inline std::vector<int16_t>& AudioSubmix::_getScratch() {
return m_scratch16;
}
template <>
inline std::vector<int32_t>& AudioSubmix::_getScratch() {
return m_scratch32;
}
template <>
inline std::vector<float>& AudioSubmix::_getScratch() {
return m_scratchFlt;
}
template <>
inline int16_t*& AudioSubmix::_getRedirect<int16_t>() {
return m_redirect16;
}
template <>
inline int32_t*& AudioSubmix::_getRedirect<int32_t>() {
return m_redirect32;
}
template <>
inline float*& AudioSubmix::_getRedirect<float>() {
return m_redirectFlt;
}
} // namespace boo

View File

@ -3,37 +3,30 @@
#include "logvisor/logvisor.hpp"
#include <cmath>
namespace boo
{
namespace boo {
static logvisor::Module Log("boo::AudioVoice");
static AudioMatrixMono DefaultMonoMtx;
static AudioMatrixStereo DefaultStereoMtx;
AudioVoice::AudioVoice(BaseAudioVoiceEngine& root,
IAudioVoiceCallback* cb, bool dynamicRate)
: ListNode<AudioVoice, BaseAudioVoiceEngine*, IAudioVoice>(&root), m_cb(cb), m_dynamicRate(dynamicRate)
{}
AudioVoice::AudioVoice(BaseAudioVoiceEngine& root, IAudioVoiceCallback* cb, bool dynamicRate)
: ListNode<AudioVoice, BaseAudioVoiceEngine*, IAudioVoice>(&root), m_cb(cb), m_dynamicRate(dynamicRate) {}
AudioVoice::~AudioVoice()
{
soxr_delete(m_src);
}
AudioVoice::~AudioVoice() { soxr_delete(m_src); }
AudioVoice*& AudioVoice::_getHeadPtr(BaseAudioVoiceEngine* head) { return head->m_voiceHead; }
std::unique_lock<std::recursive_mutex> AudioVoice::_getHeadLock(BaseAudioVoiceEngine* head)
{ return std::unique_lock<std::recursive_mutex>{head->m_dataMutex}; }
std::unique_lock<std::recursive_mutex> AudioVoice::destructorLock()
{ return std::unique_lock<std::recursive_mutex>{m_head->m_dataMutex}; }
std::unique_lock<std::recursive_mutex> AudioVoice::_getHeadLock(BaseAudioVoiceEngine* head) {
return std::unique_lock<std::recursive_mutex>{head->m_dataMutex};
}
std::unique_lock<std::recursive_mutex> AudioVoice::destructorLock() {
return std::unique_lock<std::recursive_mutex>{m_head->m_dataMutex};
}
void AudioVoice::_setPitchRatio(double ratio, bool slew)
{
if (m_dynamicRate)
{
void AudioVoice::_setPitchRatio(double ratio, bool slew) {
if (m_dynamicRate) {
m_sampleRatio = ratio * m_sampleRateIn / m_sampleRateOut;
soxr_error_t err = soxr_set_io_ratio(m_src, m_sampleRatio, slew ? m_head->m_5msFrames : 0);
if (err)
{
if (err) {
Log.report(logvisor::Fatal, "unable to set resampler rate: %s", soxr_strerror(err));
m_setPitchRatio = false;
return;
@ -42,46 +35,34 @@ void AudioVoice::_setPitchRatio(double ratio, bool slew)
m_setPitchRatio = false;
}
void AudioVoice::_midUpdate()
{
void AudioVoice::_midUpdate() {
if (m_resetSampleRate)
_resetSampleRate(m_deferredSampleRate);
if (m_setPitchRatio)
_setPitchRatio(m_pitchRatio, m_slew);
}
void AudioVoice::setPitchRatio(double ratio, bool slew)
{
void AudioVoice::setPitchRatio(double ratio, bool slew) {
m_setPitchRatio = true;
m_pitchRatio = ratio;
m_slew = slew;
}
void AudioVoice::resetSampleRate(double sampleRate)
{
void AudioVoice::resetSampleRate(double sampleRate) {
m_resetSampleRate = true;
m_deferredSampleRate = sampleRate;
}
void AudioVoice::start()
{
m_running = true;
}
void AudioVoice::start() { m_running = true; }
void AudioVoice::stop()
{
m_running = false;
}
void AudioVoice::stop() { m_running = false; }
AudioVoiceMono::AudioVoiceMono(BaseAudioVoiceEngine& root, IAudioVoiceCallback* cb,
double sampleRate, bool dynamicRate)
: AudioVoice(root, cb, dynamicRate)
{
AudioVoiceMono::AudioVoiceMono(BaseAudioVoiceEngine& root, IAudioVoiceCallback* cb, double sampleRate, bool dynamicRate)
: AudioVoice(root, cb, dynamicRate) {
_resetSampleRate(sampleRate);
}
void AudioVoiceMono::_resetSampleRate(double sampleRate)
{
void AudioVoiceMono::_resetSampleRate(double sampleRate) {
soxr_delete(m_src);
double rateOut = m_head->mixInfo().m_sampleRate;
@ -90,11 +71,9 @@ void AudioVoiceMono::_resetSampleRate(double sampleRate)
soxr_quality_spec_t qSpec = soxr_quality_spec(SOXR_20_BITQ, m_dynamicRate ? SOXR_VR : 0);
soxr_error_t err;
m_src = soxr_create(sampleRate, rateOut, 1,
&err, &ioSpec, &qSpec, nullptr);
m_src = soxr_create(sampleRate, rateOut, 1, &err, &ioSpec, &qSpec, nullptr);
if (err)
{
if (err) {
Log.report(logvisor::Fatal, "unable to create soxr resampler: %s", soxr_strerror(err));
m_resetSampleRate = false;
return;
@ -108,39 +87,31 @@ void AudioVoiceMono::_resetSampleRate(double sampleRate)
m_resetSampleRate = false;
}
size_t AudioVoiceMono::SRCCallback(AudioVoiceMono* ctx, int16_t** data, size_t frames)
{
size_t AudioVoiceMono::SRCCallback(AudioVoiceMono* ctx, int16_t** data, size_t frames) {
std::vector<int16_t>& scratchIn = ctx->m_head->m_scratchIn;
if (scratchIn.size() < frames)
scratchIn.resize(frames);
*data = scratchIn.data();
if (ctx->m_silentOut)
{
if (ctx->m_silentOut) {
memset(scratchIn.data(), 0, frames * 2);
return frames;
}
else
} else
return ctx->m_cb->supplyAudio(*ctx, frames, scratchIn.data());
}
bool AudioVoiceMono::isSilent() const
{
if (m_sendMatrices.size())
{
bool AudioVoiceMono::isSilent() const {
if (m_sendMatrices.size()) {
for (auto& mtx : m_sendMatrices)
if (!mtx.second.isSilent())
return false;
return true;
}
else
{
} else {
return DefaultMonoMtx.isSilent();
}
}
template <typename T>
size_t AudioVoiceMono::_pumpAndMix(size_t frames)
{
size_t AudioVoiceMono::_pumpAndMix(size_t frames) {
auto& scratchPre = m_head->_getScratchPre<T>();
if (scratchPre.size() < frames)
scratchPre.resize(frames + 2);
@ -153,8 +124,7 @@ size_t AudioVoiceMono::_pumpAndMix(size_t frames)
m_cb->preSupplyAudio(*this, dt);
_midUpdate();
if (isSilent())
{
if (isSilent()) {
int16_t* dummy;
SRCCallback(this, &dummy, size_t(std::ceil(frames * m_sampleRatio)));
return 0;
@ -162,38 +132,29 @@ size_t AudioVoiceMono::_pumpAndMix(size_t frames)
size_t oDone = soxr_output(m_src, scratchPre.data(), frames);
if (oDone)
{
if (m_sendMatrices.size())
{
for (auto& mtx : m_sendMatrices)
{
if (oDone) {
if (m_sendMatrices.size()) {
for (auto& mtx : m_sendMatrices) {
AudioSubmix& smx = *reinterpret_cast<AudioSubmix*>(mtx.first);
m_cb->routeAudio(oDone, 1, dt, smx.m_busId, scratchPre.data(), scratchPost.data());
mtx.second.mixMonoSampleData(m_head->clientMixInfo(), scratchPost.data(),
smx._getMergeBuf<T>(oDone), oDone);
mtx.second.mixMonoSampleData(m_head->clientMixInfo(), scratchPost.data(), smx._getMergeBuf<T>(oDone), oDone);
}
}
else
{
} else {
AudioSubmix& smx = *m_head->m_mainSubmix;
m_cb->routeAudio(oDone, 1, dt, m_head->m_mainSubmix->m_busId, scratchPre.data(), scratchPost.data());
DefaultMonoMtx.mixMonoSampleData(m_head->clientMixInfo(), scratchPost.data(),
smx._getMergeBuf<T>(oDone), oDone);
DefaultMonoMtx.mixMonoSampleData(m_head->clientMixInfo(), scratchPost.data(), smx._getMergeBuf<T>(oDone), oDone);
}
}
return oDone;
}
void AudioVoiceMono::resetChannelLevels()
{
void AudioVoiceMono::resetChannelLevels() {
m_head->m_submixesDirty = true;
m_sendMatrices.clear();
}
void AudioVoiceMono::setMonoChannelLevels(IAudioSubmix* submix, const float coefs[8], bool slew)
{
void AudioVoiceMono::setMonoChannelLevels(IAudioSubmix* submix, const float coefs[8], bool slew) {
if (!submix)
submix = m_head->m_mainSubmix.get();
@ -203,19 +164,9 @@ void AudioVoiceMono::setMonoChannelLevels(IAudioSubmix* submix, const float coef
search->second.setMatrixCoefficients(coefs, slew ? m_head->m_5msFrames : 0);
}
void AudioVoiceMono::setStereoChannelLevels(IAudioSubmix* submix, const float coefs[8][2], bool slew)
{
float newCoefs[8] =
{
coefs[0][0],
coefs[1][0],
coefs[2][0],
coefs[3][0],
coefs[4][0],
coefs[5][0],
coefs[6][0],
coefs[7][0]
};
void AudioVoiceMono::setStereoChannelLevels(IAudioSubmix* submix, const float coefs[8][2], bool slew) {
float newCoefs[8] = {coefs[0][0], coefs[1][0], coefs[2][0], coefs[3][0],
coefs[4][0], coefs[5][0], coefs[6][0], coefs[7][0]};
if (!submix)
submix = m_head->m_mainSubmix.get();
@ -226,15 +177,13 @@ void AudioVoiceMono::setStereoChannelLevels(IAudioSubmix* submix, const float co
search->second.setMatrixCoefficients(newCoefs, slew ? m_head->m_5msFrames : 0);
}
AudioVoiceStereo::AudioVoiceStereo(BaseAudioVoiceEngine& root, IAudioVoiceCallback* cb,
double sampleRate, bool dynamicRate)
: AudioVoice(root, cb, dynamicRate)
{
AudioVoiceStereo::AudioVoiceStereo(BaseAudioVoiceEngine& root, IAudioVoiceCallback* cb, double sampleRate,
bool dynamicRate)
: AudioVoice(root, cb, dynamicRate) {
_resetSampleRate(sampleRate);
}
void AudioVoiceStereo::_resetSampleRate(double sampleRate)
{
void AudioVoiceStereo::_resetSampleRate(double sampleRate) {
soxr_delete(m_src);
double rateOut = m_head->mixInfo().m_sampleRate;
@ -243,11 +192,9 @@ void AudioVoiceStereo::_resetSampleRate(double sampleRate)
soxr_quality_spec_t qSpec = soxr_quality_spec(SOXR_20_BITQ, m_dynamicRate ? SOXR_VR : 0);
soxr_error_t err;
m_src = soxr_create(sampleRate, rateOut, 2,
&err, &ioSpec, &qSpec, nullptr);
m_src = soxr_create(sampleRate, rateOut, 2, &err, &ioSpec, &qSpec, nullptr);
if (!m_src)
{
if (!m_src) {
Log.report(logvisor::Fatal, "unable to create soxr resampler: %s", soxr_strerror(err));
m_resetSampleRate = false;
return;
@ -261,40 +208,32 @@ void AudioVoiceStereo::_resetSampleRate(double sampleRate)
m_resetSampleRate = false;
}
size_t AudioVoiceStereo::SRCCallback(AudioVoiceStereo* ctx, int16_t** data, size_t frames)
{
size_t AudioVoiceStereo::SRCCallback(AudioVoiceStereo* ctx, int16_t** data, size_t frames) {
std::vector<int16_t>& scratchIn = ctx->m_head->m_scratchIn;
size_t samples = frames * 2;
if (scratchIn.size() < samples)
scratchIn.resize(samples);
*data = scratchIn.data();
if (ctx->m_silentOut)
{
if (ctx->m_silentOut) {
memset(scratchIn.data(), 0, samples * 2);
return frames;
}
else
} else
return ctx->m_cb->supplyAudio(*ctx, frames, scratchIn.data());
}
bool AudioVoiceStereo::isSilent() const
{
if (m_sendMatrices.size())
{
bool AudioVoiceStereo::isSilent() const {
if (m_sendMatrices.size()) {
for (auto& mtx : m_sendMatrices)
if (!mtx.second.isSilent())
return false;
return true;
}
else
{
} else {
return DefaultStereoMtx.isSilent();
}
}
template <typename T>
size_t AudioVoiceStereo::_pumpAndMix(size_t frames)
{
size_t AudioVoiceStereo::_pumpAndMix(size_t frames) {
size_t samples = frames * 2;
auto& scratchPre = m_head->_getScratchPre<T>();
@ -309,8 +248,7 @@ size_t AudioVoiceStereo::_pumpAndMix(size_t frames)
m_cb->preSupplyAudio(*this, dt);
_midUpdate();
if (isSilent())
{
if (isSilent()) {
int16_t* dummy;
SRCCallback(this, &dummy, size_t(std::ceil(frames * m_sampleRatio)));
return 0;
@ -318,49 +256,32 @@ size_t AudioVoiceStereo::_pumpAndMix(size_t frames)
size_t oDone = soxr_output(m_src, scratchPre.data(), frames);
if (oDone)
{
if (m_sendMatrices.size())
{
for (auto& mtx : m_sendMatrices)
{
if (oDone) {
if (m_sendMatrices.size()) {
for (auto& mtx : m_sendMatrices) {
AudioSubmix& smx = *reinterpret_cast<AudioSubmix*>(mtx.first);
m_cb->routeAudio(oDone, 2, dt, smx.m_busId, scratchPre.data(), scratchPost.data());
mtx.second.mixStereoSampleData(m_head->clientMixInfo(), scratchPost.data(),
smx._getMergeBuf<T>(oDone), oDone);
mtx.second.mixStereoSampleData(m_head->clientMixInfo(), scratchPost.data(), smx._getMergeBuf<T>(oDone), oDone);
}
}
else
{
} else {
AudioSubmix& smx = *m_head->m_mainSubmix;
m_cb->routeAudio(oDone, 2, dt, m_head->m_mainSubmix->m_busId, scratchPre.data(), scratchPost.data());
DefaultStereoMtx.mixStereoSampleData(m_head->clientMixInfo(), scratchPost.data(),
smx._getMergeBuf<T>(oDone), oDone);
DefaultStereoMtx.mixStereoSampleData(m_head->clientMixInfo(), scratchPost.data(), smx._getMergeBuf<T>(oDone),
oDone);
}
}
return oDone;
}
void AudioVoiceStereo::resetChannelLevels()
{
void AudioVoiceStereo::resetChannelLevels() {
m_head->m_submixesDirty = true;
m_sendMatrices.clear();
}
void AudioVoiceStereo::setMonoChannelLevels(IAudioSubmix* submix, const float coefs[8], bool slew)
{
float newCoefs[8][2] =
{
{coefs[0], coefs[0]},
{coefs[1], coefs[1]},
{coefs[2], coefs[2]},
{coefs[3], coefs[3]},
{coefs[4], coefs[4]},
{coefs[5], coefs[5]},
{coefs[6], coefs[6]},
{coefs[7], coefs[7]}
};
void AudioVoiceStereo::setMonoChannelLevels(IAudioSubmix* submix, const float coefs[8], bool slew) {
float newCoefs[8][2] = {{coefs[0], coefs[0]}, {coefs[1], coefs[1]}, {coefs[2], coefs[2]}, {coefs[3], coefs[3]},
{coefs[4], coefs[4]}, {coefs[5], coefs[5]}, {coefs[6], coefs[6]}, {coefs[7], coefs[7]}};
if (!submix)
submix = m_head->m_mainSubmix.get();
@ -371,8 +292,7 @@ void AudioVoiceStereo::setMonoChannelLevels(IAudioSubmix* submix, const float co
search->second.setMatrixCoefficients(newCoefs, slew ? m_head->m_5msFrames : 0);
}
void AudioVoiceStereo::setStereoChannelLevels(IAudioSubmix* submix, const float coefs[8][2], bool slew)
{
void AudioVoiceStereo::setStereoChannelLevels(IAudioSubmix* submix, const float coefs[8][2], bool slew) {
if (!submix)
submix = m_head->m_mainSubmix.get();
@ -382,4 +302,4 @@ void AudioVoiceStereo::setStereoChannelLevels(IAudioSubmix* submix, const float
search->second.setMatrixCoefficients(coefs, slew ? m_head->m_5msFrames : 0);
}
}
} // namespace boo

View File

@ -12,14 +12,12 @@ struct AudioUnitVoiceEngine;
struct VSTVoiceEngine;
struct WAVOutVoiceEngine;
namespace boo
{
namespace boo {
class BaseAudioVoiceEngine;
struct AudioVoiceEngineMixInfo;
struct IAudioSubmix;
class AudioVoice : public ListNode<AudioVoice, BaseAudioVoiceEngine*, IAudioVoice>
{
class AudioVoice : public ListNode<AudioVoice, BaseAudioVoiceEngine*, IAudioVoice> {
friend class BaseAudioVoiceEngine;
friend class AudioSubmix;
friend struct WASAPIAudioVoiceEngine;
@ -58,7 +56,8 @@ protected:
virtual size_t pumpAndMix16(size_t frames) = 0;
virtual size_t pumpAndMix32(size_t frames) = 0;
virtual size_t pumpAndMixFlt(size_t frames) = 0;
template <typename T> size_t pumpAndMix(size_t frames);
template <typename T>
size_t pumpAndMix(size_t frames);
AudioVoice(BaseAudioVoiceEngine& root, IAudioVoiceCallback* cb, bool dynamicRate);
@ -76,57 +75,61 @@ public:
double getSampleRateOut() const { return m_sampleRateOut; }
};
template <> inline size_t AudioVoice::pumpAndMix<int16_t>(size_t frames) { return pumpAndMix16(frames); }
template <> inline size_t AudioVoice::pumpAndMix<int32_t>(size_t frames) { return pumpAndMix32(frames); }
template <> inline size_t AudioVoice::pumpAndMix<float>(size_t frames) { return pumpAndMixFlt(frames); }
template <>
inline size_t AudioVoice::pumpAndMix<int16_t>(size_t frames) {
return pumpAndMix16(frames);
}
template <>
inline size_t AudioVoice::pumpAndMix<int32_t>(size_t frames) {
return pumpAndMix32(frames);
}
template <>
inline size_t AudioVoice::pumpAndMix<float>(size_t frames) {
return pumpAndMixFlt(frames);
}
class AudioVoiceMono : public AudioVoice
{
class AudioVoiceMono : public AudioVoice {
std::unordered_map<IAudioSubmix*, AudioMatrixMono> m_sendMatrices;
bool m_silentOut = false;
void _resetSampleRate(double sampleRate);
static size_t SRCCallback(AudioVoiceMono* ctx,
int16_t** data, size_t requestedLen);
static size_t SRCCallback(AudioVoiceMono* ctx, int16_t** data, size_t requestedLen);
bool isSilent() const;
template <typename T> size_t _pumpAndMix(size_t frames);
template <typename T>
size_t _pumpAndMix(size_t frames);
size_t pumpAndMix16(size_t frames) { return _pumpAndMix<int16_t>(frames); }
size_t pumpAndMix32(size_t frames) { return _pumpAndMix<int32_t>(frames); }
size_t pumpAndMixFlt(size_t frames) { return _pumpAndMix<float>(frames); }
public:
AudioVoiceMono(BaseAudioVoiceEngine& root, IAudioVoiceCallback* cb,
double sampleRate, bool dynamicRate);
AudioVoiceMono(BaseAudioVoiceEngine& root, IAudioVoiceCallback* cb, double sampleRate, bool dynamicRate);
void resetChannelLevels();
void setMonoChannelLevels(IAudioSubmix* submix, const float coefs[8], bool slew);
void setStereoChannelLevels(IAudioSubmix* submix, const float coefs[8][2], bool slew);
};
class AudioVoiceStereo : public AudioVoice
{
class AudioVoiceStereo : public AudioVoice {
std::unordered_map<IAudioSubmix*, AudioMatrixStereo> m_sendMatrices;
bool m_silentOut = false;
void _resetSampleRate(double sampleRate);
static size_t SRCCallback(AudioVoiceStereo* ctx,
int16_t** data, size_t requestedLen);
static size_t SRCCallback(AudioVoiceStereo* ctx, int16_t** data, size_t requestedLen);
bool isSilent() const;
template <typename T> size_t _pumpAndMix(size_t frames);
template <typename T>
size_t _pumpAndMix(size_t frames);
size_t pumpAndMix16(size_t frames) { return _pumpAndMix<int16_t>(frames); }
size_t pumpAndMix32(size_t frames) { return _pumpAndMix<int32_t>(frames); }
size_t pumpAndMixFlt(size_t frames) { return _pumpAndMix<float>(frames); }
public:
AudioVoiceStereo(BaseAudioVoiceEngine& root, IAudioVoiceCallback* cb,
double sampleRate, bool dynamicRate);
AudioVoiceStereo(BaseAudioVoiceEngine& root, IAudioVoiceCallback* cb, double sampleRate, bool dynamicRate);
void resetChannelLevels();
void setMonoChannelLevels(IAudioSubmix* submix, const float coefs[8], bool slew);
void setStereoChannelLevels(IAudioSubmix* submix, const float coefs[8][2], bool slew);
};
}
} // namespace boo

View File

@ -1,52 +1,41 @@
#include "AudioVoiceEngine.hpp"
#include <cassert>
namespace boo
{
namespace boo {
BaseAudioVoiceEngine::~BaseAudioVoiceEngine()
{
BaseAudioVoiceEngine::~BaseAudioVoiceEngine() {
m_mainSubmix.reset();
assert(m_voiceHead == nullptr && "Dangling voices detected");
assert(m_submixHead == nullptr && "Dangling submixes detected");
}
template <typename T>
void BaseAudioVoiceEngine::_pumpAndMixVoices(size_t frames, T* dataOut)
{
void BaseAudioVoiceEngine::_pumpAndMixVoices(size_t frames, T* dataOut) {
if (dataOut)
memset(dataOut, 0, sizeof(T) * frames * m_mixInfo.m_channelMap.m_channelCount);
if (m_ltRtProcessing)
{
if (m_ltRtProcessing) {
size_t sampleCount = m_5msFrames * 5;
if (_getLtRtIn<T>().size() < sampleCount)
_getLtRtIn<T>().resize(sampleCount);
m_mainSubmix->_getRedirect<T>() = _getLtRtIn<T>().data();
}
else
{
} else {
m_mainSubmix->_getRedirect<T>() = dataOut;
}
if (m_submixesDirty)
{
if (m_submixesDirty) {
m_linearizedSubmixes = m_mainSubmix->_linearizeC3();
m_submixesDirty = false;
}
size_t remFrames = frames;
while (remFrames)
{
while (remFrames) {
size_t thisFrames;
if (remFrames < m_5msFrames)
{
if (remFrames < m_5msFrames) {
thisFrames = remFrames;
if (m_engineCallback)
m_engineCallback->on5MsInterval(*this, thisFrames / double(m_5msFrames) * 5.0 / 1000.0);
}
else
{
} else {
thisFrames = m_5msFrames;
if (m_engineCallback)
m_engineCallback->on5MsInterval(*this, 5.0 / 1000.0);
@ -70,8 +59,7 @@ void BaseAudioVoiceEngine::_pumpAndMixVoices(size_t frames, T* dataOut)
if (!dataOut)
continue;
if (m_ltRtProcessing)
{
if (m_ltRtProcessing) {
m_ltRtProcessing->Process(_getLtRtIn<T>().data(), dataOut, int(thisFrames));
m_mainSubmix->_getRedirect<T>() = _getLtRtIn<T>().data();
}
@ -91,8 +79,7 @@ template void BaseAudioVoiceEngine::_pumpAndMixVoices<int16_t>(size_t frames, in
template void BaseAudioVoiceEngine::_pumpAndMixVoices<int32_t>(size_t frames, int32_t* dataOut);
template void BaseAudioVoiceEngine::_pumpAndMixVoices<float>(size_t frames, float* dataOut);
void BaseAudioVoiceEngine::_resetSampleRate()
{
void BaseAudioVoiceEngine::_resetSampleRate() {
if (m_voiceHead)
for (boo::AudioVoice& vox : *m_voiceHead)
vox._resetSampleRate(vox.m_sampleRateIn);
@ -101,56 +88,36 @@ void BaseAudioVoiceEngine::_resetSampleRate()
smx._resetOutputSampleRate();
}
ObjToken<IAudioVoice>
BaseAudioVoiceEngine::allocateNewMonoVoice(double sampleRate,
IAudioVoiceCallback* cb,
bool dynamicPitch)
{
ObjToken<IAudioVoice> BaseAudioVoiceEngine::allocateNewMonoVoice(double sampleRate, IAudioVoiceCallback* cb,
bool dynamicPitch) {
return {new AudioVoiceMono(*this, cb, sampleRate, dynamicPitch)};
}
ObjToken<IAudioVoice>
BaseAudioVoiceEngine::allocateNewStereoVoice(double sampleRate,
IAudioVoiceCallback* cb,
bool dynamicPitch)
{
ObjToken<IAudioVoice> BaseAudioVoiceEngine::allocateNewStereoVoice(double sampleRate, IAudioVoiceCallback* cb,
bool dynamicPitch) {
return {new AudioVoiceStereo(*this, cb, sampleRate, dynamicPitch)};
}
ObjToken<IAudioSubmix>
BaseAudioVoiceEngine::allocateNewSubmix(bool mainOut, IAudioSubmixCallback* cb, int busId)
{
ObjToken<IAudioSubmix> BaseAudioVoiceEngine::allocateNewSubmix(bool mainOut, IAudioSubmixCallback* cb, int busId) {
return {new AudioSubmix(*this, cb, busId, mainOut)};
}
void BaseAudioVoiceEngine::setCallbackInterface(IAudioVoiceEngineCallback* cb)
{
m_engineCallback = cb;
}
void BaseAudioVoiceEngine::setCallbackInterface(IAudioVoiceEngineCallback* cb) { m_engineCallback = cb; }
void BaseAudioVoiceEngine::setVolume(float vol)
{
m_totalVol = vol;
}
void BaseAudioVoiceEngine::setVolume(float vol) { m_totalVol = vol; }
bool BaseAudioVoiceEngine::enableLtRt(bool enable)
{
if (enable && m_mixInfo.m_channelMap.m_channelCount == 2 &&
m_mixInfo.m_channels == AudioChannelSet::Stereo)
bool BaseAudioVoiceEngine::enableLtRt(bool enable) {
if (enable && m_mixInfo.m_channelMap.m_channelCount == 2 && m_mixInfo.m_channels == AudioChannelSet::Stereo)
m_ltRtProcessing = std::make_unique<LtRtProcessing>(m_5msFrames, m_mixInfo);
else
m_ltRtProcessing.reset();
return m_ltRtProcessing.operator bool();
}
const AudioVoiceEngineMixInfo& BaseAudioVoiceEngine::mixInfo() const
{
return m_mixInfo;
}
const AudioVoiceEngineMixInfo& BaseAudioVoiceEngine::mixInfo() const { return m_mixInfo; }
const AudioVoiceEngineMixInfo& BaseAudioVoiceEngine::clientMixInfo() const
{
const AudioVoiceEngineMixInfo& BaseAudioVoiceEngine::clientMixInfo() const {
return m_ltRtProcessing ? m_ltRtProcessing->inMixInfo() : m_mixInfo;
}
}
} // namespace boo

View File

@ -8,12 +8,10 @@
#include <functional>
#include <mutex>
namespace boo
{
namespace boo {
/** Base class for managing mixing and sample-rate-conversion amongst active voices */
class BaseAudioVoiceEngine : public IAudioVoiceEngine
{
class BaseAudioVoiceEngine : public IAudioVoiceEngine {
protected:
friend class AudioVoice;
friend class AudioSubmix;
@ -32,18 +30,21 @@ protected:
std::vector<int16_t> m_scratch16Pre;
std::vector<int32_t> m_scratch32Pre;
std::vector<float> m_scratchFltPre;
template <typename T> std::vector<T>& _getScratchPre();
template <typename T>
std::vector<T>& _getScratchPre();
std::vector<int16_t> m_scratch16Post;
std::vector<int32_t> m_scratch32Post;
std::vector<float> m_scratchFltPost;
template <typename T> std::vector<T>& _getScratchPost();
template <typename T>
std::vector<T>& _getScratchPost();
/* LtRt processing if enabled */
std::unique_ptr<LtRtProcessing> m_ltRtProcessing;
std::vector<int16_t> m_ltRtIn16;
std::vector<int32_t> m_ltRtIn32;
std::vector<float> m_ltRtInFlt;
template <typename T> std::vector<T>& _getLtRtIn();
template <typename T>
std::vector<T>& _getLtRtIn();
std::unique_ptr<AudioSubmix> m_mainSubmix;
std::list<AudioSubmix*> m_linearizedSubmixes;
@ -57,13 +58,9 @@ protected:
public:
BaseAudioVoiceEngine() : m_mainSubmix(std::make_unique<AudioSubmix>(*this, nullptr, -1, false)) {}
~BaseAudioVoiceEngine();
ObjToken<IAudioVoice> allocateNewMonoVoice(double sampleRate,
IAudioVoiceCallback* cb,
bool dynamicPitch=false);
ObjToken<IAudioVoice> allocateNewMonoVoice(double sampleRate, IAudioVoiceCallback* cb, bool dynamicPitch = false);
ObjToken<IAudioVoice> allocateNewStereoVoice(double sampleRate,
IAudioVoiceCallback* cb,
bool dynamicPitch=false);
ObjToken<IAudioVoice> allocateNewStereoVoice(double sampleRate, IAudioVoiceCallback* cb, bool dynamicPitch = false);
ObjToken<IAudioSubmix> allocateNewSubmix(bool mainOut, IAudioSubmixCallback* cb, int busId);
@ -78,17 +75,43 @@ public:
size_t get5MsFrames() const { return m_5msFrames; }
};
template <> inline std::vector<int16_t>& BaseAudioVoiceEngine::_getScratchPre<int16_t>() { return m_scratch16Pre; }
template <> inline std::vector<int32_t>& BaseAudioVoiceEngine::_getScratchPre<int32_t>() { return m_scratch32Pre; }
template <> inline std::vector<float>& BaseAudioVoiceEngine::_getScratchPre<float>() { return m_scratchFltPre; }
template <> inline std::vector<int16_t>& BaseAudioVoiceEngine::_getScratchPost<int16_t>() { return m_scratch16Post; }
template <> inline std::vector<int32_t>& BaseAudioVoiceEngine::_getScratchPost<int32_t>() { return m_scratch32Post; }
template <> inline std::vector<float>& BaseAudioVoiceEngine::_getScratchPost<float>() { return m_scratchFltPost; }
template <> inline std::vector<int16_t>& BaseAudioVoiceEngine::_getLtRtIn<int16_t>() { return m_ltRtIn16; }
template <> inline std::vector<int32_t>& BaseAudioVoiceEngine::_getLtRtIn<int32_t>() { return m_ltRtIn32; }
template <> inline std::vector<float>& BaseAudioVoiceEngine::_getLtRtIn<float>() { return m_ltRtInFlt; }
template <>
inline std::vector<int16_t>& BaseAudioVoiceEngine::_getScratchPre<int16_t>() {
return m_scratch16Pre;
}
template <>
inline std::vector<int32_t>& BaseAudioVoiceEngine::_getScratchPre<int32_t>() {
return m_scratch32Pre;
}
template <>
inline std::vector<float>& BaseAudioVoiceEngine::_getScratchPre<float>() {
return m_scratchFltPre;
}
template <>
inline std::vector<int16_t>& BaseAudioVoiceEngine::_getScratchPost<int16_t>() {
return m_scratch16Post;
}
template <>
inline std::vector<int32_t>& BaseAudioVoiceEngine::_getScratchPost<int32_t>() {
return m_scratch32Post;
}
template <>
inline std::vector<float>& BaseAudioVoiceEngine::_getScratchPost<float>() {
return m_scratchFltPost;
}
template <>
inline std::vector<int16_t>& BaseAudioVoiceEngine::_getLtRtIn<int16_t>() {
return m_ltRtIn16;
}
template <>
inline std::vector<int32_t>& BaseAudioVoiceEngine::_getLtRtIn<int32_t>() {
return m_ltRtIn32;
}
template <>
inline std::vector<float>& BaseAudioVoiceEngine::_getLtRtIn<float>() {
return m_ltRtInFlt;
}
} // namespace boo

View File

@ -4,12 +4,10 @@
#include "../Common.hpp"
#include "boo/audiodev/IAudioVoice.hpp"
namespace boo
{
namespace boo {
/** Pertinent information from audio backend about optimal mixed-audio representation */
struct AudioVoiceEngineMixInfo
{
struct AudioVoiceEngineMixInfo {
double m_sampleRate = 32000.0;
soxr_datatype_t m_sampleFormat = SOXR_FLOAT32_I;
unsigned m_bitsPerSample = 32;
@ -18,5 +16,4 @@ struct AudioVoiceEngineMixInfo
size_t m_periodFrames = 160;
};
}
} // namespace boo

View File

@ -7,28 +7,17 @@
#include <alsa/asoundlib.h>
#include <signal.h>
namespace boo
{
namespace boo {
extern logvisor::Module ALSALog;
static inline double TimespecToDouble(struct timespec& ts)
{
return ts.tv_sec + ts.tv_nsec / 1.0e9;
}
static inline double TimespecToDouble(struct timespec& ts) { return ts.tv_sec + ts.tv_nsec / 1.0e9; }
struct LinuxMidi : BaseAudioVoiceEngine
{
struct LinuxMidi : BaseAudioVoiceEngine {
std::unordered_map<std::string, IMIDIPort*> m_openHandles;
void _addOpenHandle(const char* name, IMIDIPort* port)
{
m_openHandles[name] = port;
}
void _removeOpenHandle(IMIDIPort* port)
{
for (auto it = m_openHandles.begin(); it != m_openHandles.end();)
{
if (it->second == port)
{
void _addOpenHandle(const char* name, IMIDIPort* port) { m_openHandles[name] = port; }
void _removeOpenHandle(IMIDIPort* port) {
for (auto it = m_openHandles.begin(); it != m_openHandles.end();) {
if (it->second == port) {
it = m_openHandles.erase(it);
continue;
}
@ -36,14 +25,12 @@ struct LinuxMidi : BaseAudioVoiceEngine
}
}
~LinuxMidi()
{
~LinuxMidi() {
for (auto& p : m_openHandles)
p.second->_disown();
}
std::vector<std::pair<std::string, std::string>> enumerateMIDIInputs() const
{
std::vector<std::pair<std::string, std::string>> enumerateMIDIInputs() const {
std::vector<std::pair<std::string, std::string>> ret;
int status;
int card = -1; /* use -1 to prime the pump of iterating through card list */
@ -56,8 +43,7 @@ struct LinuxMidi : BaseAudioVoiceEngine
snd_rawmidi_info_t* info;
snd_rawmidi_info_malloc(&info);
while (card >= 0)
{
while (card >= 0) {
snd_ctl_t* ctl;
char name[32];
int device = -1;
@ -70,19 +56,16 @@ struct LinuxMidi : BaseAudioVoiceEngine
status = snd_ctl_rawmidi_next_device(ctl, &device);
if (status < 0)
break;
if (device >= 0)
{
if (device >= 0) {
sprintf(name + strlen(name), ",%d", device);
auto search = m_openHandles.find(name);
if (search != m_openHandles.cend())
{
if (search != m_openHandles.cend()) {
ret.push_back(std::make_pair(name, search->second->description()));
continue;
}
snd_rawmidi_t* midi;
if (!snd_rawmidi_open(&midi, nullptr, name, SND_RAWMIDI_NONBLOCK))
{
if (!snd_rawmidi_open(&midi, nullptr, name, SND_RAWMIDI_NONBLOCK)) {
snd_rawmidi_info(midi, info);
ret.push_back(std::make_pair(name, snd_rawmidi_info_get_name(info)));
snd_rawmidi_close(midi);
@ -101,34 +84,24 @@ struct LinuxMidi : BaseAudioVoiceEngine
return ret;
}
bool supportsVirtualMIDIIn() const
{
return true;
}
bool supportsVirtualMIDIIn() const { return true; }
static void MIDIFreeProc(void* midiStatus)
{
snd_rawmidi_status_free((snd_rawmidi_status_t*)midiStatus);
}
static void MIDIFreeProc(void* midiStatus) { snd_rawmidi_status_free((snd_rawmidi_status_t*)midiStatus); }
static void MIDIReceiveProc(snd_rawmidi_t* midi, const ReceiveFunctor& receiver)
{
static void MIDIReceiveProc(snd_rawmidi_t* midi, const ReceiveFunctor& receiver) {
logvisor::RegisterThreadName("Boo MIDI");
snd_rawmidi_status_t* midiStatus;
snd_rawmidi_status_malloc(&midiStatus);
pthread_cleanup_push(MIDIFreeProc, midiStatus);
uint8_t buf[512];
while (true)
{
while (true) {
snd_htimestamp_t ts;
snd_rawmidi_status(midi, midiStatus);
snd_rawmidi_status_get_tstamp(midiStatus, &ts);
int rdBytes = snd_rawmidi_read(midi, buf, 512);
if (rdBytes < 0)
{
if (rdBytes != -EINTR)
{
if (rdBytes < 0) {
if (rdBytes != -EINTR) {
ALSALog.report(logvisor::Error, "MIDI connection lost");
break;
}
@ -145,17 +118,16 @@ struct LinuxMidi : BaseAudioVoiceEngine
pthread_cleanup_pop(1);
}
struct MIDIIn : public IMIDIIn
{
struct MIDIIn : public IMIDIIn {
snd_rawmidi_t* m_midi;
std::thread m_midiThread;
MIDIIn(LinuxMidi* parent, snd_rawmidi_t* midi, bool virt, ReceiveFunctor&& receiver)
: IMIDIIn(parent, virt, std::move(receiver)), m_midi(midi),
m_midiThread(std::bind(MIDIReceiveProc, m_midi, m_receiver)) {}
: IMIDIIn(parent, virt, std::move(receiver))
, m_midi(midi)
, m_midiThread(std::bind(MIDIReceiveProc, m_midi, m_receiver)) {}
~MIDIIn()
{
~MIDIIn() {
if (m_parent)
static_cast<LinuxMidi*>(m_parent)->_removeOpenHandle(this);
pthread_cancel(m_midiThread.native_handle());
@ -164,8 +136,7 @@ struct LinuxMidi : BaseAudioVoiceEngine
snd_rawmidi_close(m_midi);
}
std::string description() const
{
std::string description() const {
snd_rawmidi_info_t* info;
snd_rawmidi_info_alloca(&info);
snd_rawmidi_info(m_midi, info);
@ -174,21 +145,17 @@ struct LinuxMidi : BaseAudioVoiceEngine
}
};
struct MIDIOut : public IMIDIOut
{
struct MIDIOut : public IMIDIOut {
snd_rawmidi_t* m_midi;
MIDIOut(LinuxMidi* parent, snd_rawmidi_t* midi, bool virt)
: IMIDIOut(parent, virt), m_midi(midi) {}
MIDIOut(LinuxMidi* parent, snd_rawmidi_t* midi, bool virt) : IMIDIOut(parent, virt), m_midi(midi) {}
~MIDIOut()
{
~MIDIOut() {
if (m_parent)
static_cast<LinuxMidi*>(m_parent)->_removeOpenHandle(this);
snd_rawmidi_close(m_midi);
}
std::string description() const
{
std::string description() const {
snd_rawmidi_info_t* info;
snd_rawmidi_info_alloca(&info);
snd_rawmidi_info(m_midi, info);
@ -196,24 +163,21 @@ struct LinuxMidi : BaseAudioVoiceEngine
return ret;
}
size_t send(const void* buf, size_t len) const
{
return size_t(std::max(0l, snd_rawmidi_write(m_midi, buf, len)));
}
size_t send(const void* buf, size_t len) const { return size_t(std::max(0l, snd_rawmidi_write(m_midi, buf, len))); }
};
struct MIDIInOut : public IMIDIInOut
{
struct MIDIInOut : public IMIDIInOut {
snd_rawmidi_t* m_midiIn;
snd_rawmidi_t* m_midiOut;
std::thread m_midiThread;
MIDIInOut(LinuxMidi* parent, snd_rawmidi_t* midiIn, snd_rawmidi_t* midiOut, bool virt, ReceiveFunctor&& receiver)
: IMIDIInOut(parent, virt, std::move(receiver)), m_midiIn(midiIn), m_midiOut(midiOut),
m_midiThread(std::bind(MIDIReceiveProc, m_midiIn, m_receiver)) {}
: IMIDIInOut(parent, virt, std::move(receiver))
, m_midiIn(midiIn)
, m_midiOut(midiOut)
, m_midiThread(std::bind(MIDIReceiveProc, m_midiIn, m_receiver)) {}
~MIDIInOut()
{
~MIDIInOut() {
if (m_parent)
static_cast<LinuxMidi*>(m_parent)->_removeOpenHandle(this);
pthread_cancel(m_midiThread.native_handle());
@ -223,8 +187,7 @@ struct LinuxMidi : BaseAudioVoiceEngine
snd_rawmidi_close(m_midiOut);
}
std::string description() const
{
std::string description() const {
snd_rawmidi_info_t* info;
snd_rawmidi_info_alloca(&info);
snd_rawmidi_info(m_midiIn, info);
@ -232,14 +195,12 @@ struct LinuxMidi : BaseAudioVoiceEngine
return ret;
}
size_t send(const void* buf, size_t len) const
{
size_t send(const void* buf, size_t len) const {
return size_t(std::max(0l, snd_rawmidi_write(m_midiOut, buf, len)));
}
};
std::unique_ptr<IMIDIIn> newVirtualMIDIIn(ReceiveFunctor&& receiver)
{
std::unique_ptr<IMIDIIn> newVirtualMIDIIn(ReceiveFunctor&& receiver) {
int status;
snd_rawmidi_t* midi;
status = snd_rawmidi_open(&midi, nullptr, "virtual", 0);
@ -248,8 +209,7 @@ struct LinuxMidi : BaseAudioVoiceEngine
return std::make_unique<MIDIIn>(nullptr, midi, true, std::move(receiver));
}
std::unique_ptr<IMIDIOut> newVirtualMIDIOut()
{
std::unique_ptr<IMIDIOut> newVirtualMIDIOut() {
int status;
snd_rawmidi_t* midi;
status = snd_rawmidi_open(nullptr, &midi, "virtual", 0);
@ -258,8 +218,7 @@ struct LinuxMidi : BaseAudioVoiceEngine
return std::make_unique<MIDIOut>(nullptr, midi, true);
}
std::unique_ptr<IMIDIInOut> newVirtualMIDIInOut(ReceiveFunctor&& receiver)
{
std::unique_ptr<IMIDIInOut> newVirtualMIDIInOut(ReceiveFunctor&& receiver) {
int status;
snd_rawmidi_t* midiIn;
snd_rawmidi_t* midiOut;
@ -269,8 +228,7 @@ struct LinuxMidi : BaseAudioVoiceEngine
return std::make_unique<MIDIInOut>(nullptr, midiIn, midiOut, true, std::move(receiver));
}
std::unique_ptr<IMIDIIn> newRealMIDIIn(const char* name, ReceiveFunctor&& receiver)
{
std::unique_ptr<IMIDIIn> newRealMIDIIn(const char* name, ReceiveFunctor&& receiver) {
snd_rawmidi_t* midi;
int status = snd_rawmidi_open(&midi, nullptr, name, 0);
if (status)
@ -280,8 +238,7 @@ struct LinuxMidi : BaseAudioVoiceEngine
return ret;
}
std::unique_ptr<IMIDIOut> newRealMIDIOut(const char* name)
{
std::unique_ptr<IMIDIOut> newRealMIDIOut(const char* name) {
snd_rawmidi_t* midi;
int status = snd_rawmidi_open(nullptr, &midi, name, 0);
if (status)
@ -291,8 +248,7 @@ struct LinuxMidi : BaseAudioVoiceEngine
return ret;
}
std::unique_ptr<IMIDIInOut> newRealMIDIInOut(const char* name, ReceiveFunctor&& receiver)
{
std::unique_ptr<IMIDIInOut> newRealMIDIInOut(const char* name, ReceiveFunctor&& receiver) {
snd_rawmidi_t* midiIn;
snd_rawmidi_t* midiOut;
int status = snd_rawmidi_open(&midiIn, &midiOut, name, 0);
@ -306,5 +262,4 @@ struct LinuxMidi : BaseAudioVoiceEngine
bool useMIDILock() const { return true; }
};
}
} // namespace boo

View File

@ -5,18 +5,13 @@
#undef min
#undef max
namespace boo
{
namespace boo {
template <typename T>
inline T ClampFull(float in)
{
if(std::is_floating_point<T>())
{
inline T ClampFull(float in) {
if (std::is_floating_point<T>()) {
return std::min<T>(std::max<T>(in, -1.f), 1.f);
}
else
{
} else {
constexpr T MAX = std::numeric_limits<T>::max();
constexpr T MIN = std::numeric_limits<T>::min();
@ -38,8 +33,7 @@ inline T ClampFull(float in)
#if USE_LPF
static constexpr int FirTaps = 27;
FIRFilter12k::FIRFilter12k(int windowFrames, double sampleRate)
{
FIRFilter12k::FIRFilter12k(int windowFrames, double sampleRate) {
Ipp64f* taps = ippsMalloc_64f(FirTaps);
Ipp32f* taps32 = ippsMalloc_32f(FirTaps);
int sizeSpec, sizeBuf;
@ -62,32 +56,31 @@ FIRFilter12k::FIRFilter12k(int windowFrames, double sampleRate)
m_inBuf = ippsMalloc_32f(windowFrames);
}
FIRFilter12k::~FIRFilter12k()
{
FIRFilter12k::~FIRFilter12k() {
ippsFree(m_firSpec);
ippsFree(m_firBuffer);
ippsFree(m_dlySrc);
ippsFree(m_inBuf);
}
void FIRFilter12k::Process(Ipp32f* buf, int windowFrames)
{
void FIRFilter12k::Process(Ipp32f* buf, int windowFrames) {
ippsZero_32f(m_dlySrc, FirTaps);
ippsMove_32f(buf, m_inBuf, windowFrames);
ippsFIRSR_32f(m_inBuf, buf, windowFrames, m_firSpec, m_dlySrc, nullptr, m_firBuffer);
}
#endif
WindowedHilbert::WindowedHilbert(int windowFrames, double sampleRate) :
WindowedHilbert::WindowedHilbert(int windowFrames, double sampleRate)
:
#if USE_LPF
m_fir(windowFrames, sampleRate),
m_fir(windowFrames, sampleRate)
,
#endif
m_windowFrames(windowFrames),
m_halfFrames(windowFrames / 2),
m_inputBuf(ippsMalloc_32f(m_windowFrames * 2 + m_halfFrames)),
m_outputBuf(ippsMalloc_32fc(m_windowFrames * 4)),
m_hammingTable(ippsMalloc_32f(m_halfFrames))
{
m_windowFrames(windowFrames)
, m_halfFrames(windowFrames / 2)
, m_inputBuf(ippsMalloc_32f(m_windowFrames * 2 + m_halfFrames))
, m_outputBuf(ippsMalloc_32fc(m_windowFrames * 4))
, m_hammingTable(ippsMalloc_32f(m_halfFrames)) {
ippsZero_32f(m_inputBuf, m_windowFrames * 2 + m_halfFrames);
ippsZero_32fc(m_outputBuf, m_windowFrames * 4);
m_output[0] = m_outputBuf;
@ -104,8 +97,7 @@ WindowedHilbert::WindowedHilbert(int windowFrames, double sampleRate) :
m_hammingTable[i] = Ipp32f(std::cos(M_PI * (i / double(m_halfFrames) + 1.0)) * 0.5 + 0.5);
}
WindowedHilbert::~WindowedHilbert()
{
WindowedHilbert::~WindowedHilbert() {
ippFree(m_spec);
ippFree(m_buffer);
ippsFree(m_inputBuf);
@ -113,51 +105,40 @@ WindowedHilbert::~WindowedHilbert()
ippsFree(m_hammingTable);
}
void WindowedHilbert::_AddWindow()
{
void WindowedHilbert::_AddWindow() {
#if USE_LPF
Ipp32f* inBufBase = &m_inputBuf[m_windowFrames * m_bufIdx + m_halfFrames];
m_fir.Process(inBufBase, m_windowFrames);
#endif
if (m_bufIdx)
{
if (m_bufIdx) {
/* Mirror last half of samples to start of input buffer */
Ipp32f* bufBase = &m_inputBuf[m_windowFrames * 2];
ippsCopy_32f(bufBase, m_inputBuf, m_halfFrames);
ippsHilbert_32f32fc(&m_inputBuf[m_windowFrames],
m_output[2], m_spec, m_buffer);
ippsHilbert_32f32fc(&m_inputBuf[m_windowFrames + m_halfFrames],
m_output[3], m_spec, m_buffer);
}
else
{
ippsHilbert_32f32fc(&m_inputBuf[0],
m_output[0], m_spec, m_buffer);
ippsHilbert_32f32fc(&m_inputBuf[m_halfFrames],
m_output[1], m_spec, m_buffer);
ippsHilbert_32f32fc(&m_inputBuf[m_windowFrames], m_output[2], m_spec, m_buffer);
ippsHilbert_32f32fc(&m_inputBuf[m_windowFrames + m_halfFrames], m_output[3], m_spec, m_buffer);
} else {
ippsHilbert_32f32fc(&m_inputBuf[0], m_output[0], m_spec, m_buffer);
ippsHilbert_32f32fc(&m_inputBuf[m_halfFrames], m_output[1], m_spec, m_buffer);
}
m_bufIdx ^= 1;
}
void WindowedHilbert::AddWindow(const float* input, int stride)
{
void WindowedHilbert::AddWindow(const float* input, int stride) {
Ipp32f* bufBase = &m_inputBuf[m_windowFrames * m_bufIdx + m_halfFrames];
for (int i = 0; i < m_windowFrames; ++i)
bufBase[i] = input[i * stride];
_AddWindow();
}
void WindowedHilbert::AddWindow(const int32_t* input, int stride)
{
void WindowedHilbert::AddWindow(const int32_t* input, int stride) {
Ipp32f* bufBase = &m_inputBuf[m_windowFrames * m_bufIdx + m_halfFrames];
for (int i = 0; i < m_windowFrames; ++i)
bufBase[i] = input[i * stride] / (float(INT32_MAX) + 1.f);
_AddWindow();
}
void WindowedHilbert::AddWindow(const int16_t* input, int stride)
{
void WindowedHilbert::AddWindow(const int16_t* input, int stride) {
Ipp32f* bufBase = &m_inputBuf[m_windowFrames * m_bufIdx + m_halfFrames];
for (int i = 0; i < m_windowFrames; ++i)
bufBase[i] = input[i * stride] / (float(INT16_MAX) + 1.f);
@ -165,17 +146,13 @@ void WindowedHilbert::AddWindow(const int16_t* input, int stride)
}
template <typename T>
void WindowedHilbert::Output(T* output, float lCoef, float rCoef) const
{
void WindowedHilbert::Output(T* output, float lCoef, float rCoef) const {
int first, middle, last;
if (m_bufIdx)
{
if (m_bufIdx) {
first = 3;
middle = 0;
last = 1;
}
else
{
} else {
first = 1;
middle = 2;
last = 3;
@ -192,23 +169,19 @@ void WindowedHilbert::Output(T* output, float lCoef, float rCoef) const
#endif
int i, t;
for (i=0, t=0 ; i<m_halfFrames ; ++i, ++t)
{
float tmp = m_output[first][m_halfFrames + i].im * (1.f - m_hammingTable[t]) +
m_output[middle][i].im * m_hammingTable[t];
for (i = 0, t = 0; i < m_halfFrames; ++i, ++t) {
float tmp =
m_output[first][m_halfFrames + i].im * (1.f - m_hammingTable[t]) + m_output[middle][i].im * m_hammingTable[t];
output[i * 2] = ClampFull<T>(output[i * 2] + tmp * lCoef);
output[i * 2 + 1] = ClampFull<T>(output[i * 2 + 1] + tmp * rCoef);
}
for (; i<m_windowFrames-m_halfFrames ; ++i)
{
for (; i < m_windowFrames - m_halfFrames; ++i) {
float tmp = m_output[middle][i].im;
output[i * 2] = ClampFull<T>(output[i * 2] + tmp * lCoef);
output[i * 2 + 1] = ClampFull<T>(output[i * 2 + 1] + tmp * rCoef);
}
for (t=0 ; i<m_windowFrames ; ++i, ++t)
{
float tmp = m_output[middle][i].im * (1.f - m_hammingTable[t]) +
m_output[last][t].im * m_hammingTable[t];
for (t = 0; i < m_windowFrames; ++i, ++t) {
float tmp = m_output[middle][i].im * (1.f - m_hammingTable[t]) + m_output[last][t].im * m_hammingTable[t];
output[i * 2] = ClampFull<T>(output[i * 2] + tmp * lCoef);
output[i * 2 + 1] = ClampFull<T>(output[i * 2 + 1] + tmp * rCoef);
}
@ -220,20 +193,40 @@ template void WindowedHilbert::Output<float>(float* output, float lCoef, float r
#endif
template <> int16_t* LtRtProcessing::_getInBuf<int16_t>() { return m_16Buffer.get(); }
template <> int32_t* LtRtProcessing::_getInBuf<int32_t>() { return m_32Buffer.get(); }
template <> float* LtRtProcessing::_getInBuf<float>() { return m_fltBuffer.get(); }
template <>
int16_t* LtRtProcessing::_getInBuf<int16_t>() {
return m_16Buffer.get();
}
template <>
int32_t* LtRtProcessing::_getInBuf<int32_t>() {
return m_32Buffer.get();
}
template <>
float* LtRtProcessing::_getInBuf<float>() {
return m_fltBuffer.get();
}
template <> int16_t* LtRtProcessing::_getOutBuf<int16_t>() { return m_16Buffer.get() + m_outputOffset; }
template <> int32_t* LtRtProcessing::_getOutBuf<int32_t>() { return m_32Buffer.get() + m_outputOffset; }
template <> float* LtRtProcessing::_getOutBuf<float>() { return m_fltBuffer.get() + m_outputOffset; }
template <>
int16_t* LtRtProcessing::_getOutBuf<int16_t>() {
return m_16Buffer.get() + m_outputOffset;
}
template <>
int32_t* LtRtProcessing::_getOutBuf<int32_t>() {
return m_32Buffer.get() + m_outputOffset;
}
template <>
float* LtRtProcessing::_getOutBuf<float>() {
return m_fltBuffer.get() + m_outputOffset;
}
LtRtProcessing::LtRtProcessing(int _5msFrames, const AudioVoiceEngineMixInfo& mixInfo)
: m_inMixInfo(mixInfo), m_windowFrames(_5msFrames * 4), m_halfFrames(m_windowFrames / 2),
m_outputOffset(m_windowFrames * 5 * 2)
: m_inMixInfo(mixInfo)
, m_windowFrames(_5msFrames * 4)
, m_halfFrames(m_windowFrames / 2)
, m_outputOffset(m_windowFrames * 5 * 2)
#if INTEL_IPP
, m_hilbertSL(m_windowFrames, mixInfo.m_sampleRate),
m_hilbertSR(m_windowFrames, mixInfo.m_sampleRate)
, m_hilbertSL(m_windowFrames, mixInfo.m_sampleRate)
, m_hilbertSR(m_windowFrames, mixInfo.m_sampleRate)
#endif
{
m_inMixInfo.m_channels = AudioChannelSet::Surround51;
@ -245,8 +238,7 @@ LtRtProcessing::LtRtProcessing(int _5msFrames, const AudioVoiceEngineMixInfo& mi
m_inMixInfo.m_channelMap.m_channels[4] = AudioChannel::RearRight;
int samples = m_windowFrames * (5 * 2 + 2 * 2);
switch (mixInfo.m_sampleFormat)
{
switch (mixInfo.m_sampleFormat) {
case SOXR_INT16_I:
m_16Buffer.reset(new int16_t[samples]);
memset(m_16Buffer.get(), 0, sizeof(int16_t) * samples);
@ -265,8 +257,7 @@ LtRtProcessing::LtRtProcessing(int _5msFrames, const AudioVoiceEngineMixInfo& mi
}
template <typename T>
void LtRtProcessing::Process(const T* input, T* output, int frameCount)
{
void LtRtProcessing::Process(const T* input, T* output, int frameCount) {
#if 0
for (int i=0 ; i<frameCount ; ++i)
{
@ -294,8 +285,7 @@ void LtRtProcessing::Process(const T* input, T* output, int frameCount)
outFramesRem -= head - m_bufferHead;
int bufIdx = m_bufferTail / m_windowFrames;
if (tail / m_windowFrames > bufIdx)
{
if (tail / m_windowFrames > bufIdx) {
T* in = &inBuf[bufIdx * m_windowFrames * 5];
T* out = &outBuf[bufIdx * m_windowFrames * 2];
#if INTEL_IPP
@ -305,29 +295,23 @@ void LtRtProcessing::Process(const T* input, T* output, int frameCount)
// x(:,1) + sqrt(.5)*x(:,3) + sqrt(19/25)*x(:,4) + sqrt(6/25)*x(:,5)
// x(:,2) + sqrt(.5)*x(:,3) - sqrt(6/25)*x(:,4) - sqrt(19/25)*x(:,5)
if (bufIdx)
{
if (bufIdx) {
int delayI = -m_halfFrames;
for (int i=0 ; i<m_windowFrames ; ++i, ++delayI)
{
for (int i = 0; i < m_windowFrames; ++i, ++delayI) {
out[i * 2] = ClampFull<T>(in[delayI * 5] + 0.7071068f * in[delayI * 5 + 2]);
out[i * 2 + 1] = ClampFull<T>(in[delayI * 5 + 1] + 0.7071068f * in[delayI * 5 + 2]);
// printf("in %d out %d\n", bufIdx * m_5msFrames + delayI, bufIdx * m_5msFrames + i);
}
}
else
{
} else {
int delayI = m_windowFrames * 2 - m_halfFrames;
int i;
for (i=0 ; i<m_halfFrames ; ++i, ++delayI)
{
for (i = 0; i < m_halfFrames; ++i, ++delayI) {
out[i * 2] = ClampFull<T>(in[delayI * 5] + 0.7071068f * in[delayI * 5 + 2]);
out[i * 2 + 1] = ClampFull<T>(in[delayI * 5 + 1] + 0.7071068f * in[delayI * 5 + 2]);
// printf("in %d out %d\n", bufIdx * m_5msFrames + delayI, bufIdx * m_5msFrames + i);
}
delayI = 0;
for (; i<m_windowFrames ; ++i, ++delayI)
{
for (; i < m_windowFrames; ++i, ++delayI) {
out[i * 2] = ClampFull<T>(in[delayI * 5] + 0.7071068f * in[delayI * 5 + 2]);
out[i * 2 + 1] = ClampFull<T>(in[delayI * 5 + 1] + 0.7071068f * in[delayI * 5 + 2]);
// printf("in %d out %d\n", bufIdx * m_5msFrames + delayI, bufIdx * m_5msFrames + i);
@ -341,16 +325,14 @@ void LtRtProcessing::Process(const T* input, T* output, int frameCount)
m_bufferTail = (tail == m_windowFrames * 2) ? 0 : tail;
m_bufferHead = (head == m_windowFrames * 2) ? 0 : head;
if (frameCount)
{
if (frameCount) {
samples = frameCount * 5;
memmove(inBuf, input, samples * sizeof(T));
// printf("input %d to %d\n", frameCount, 0);
m_bufferTail = frameCount;
}
if (outFramesRem)
{
if (outFramesRem) {
samples = outFramesRem * 2;
memmove(output, outBuf, samples * sizeof(T));
// printf("output %d from %d\n", outFramesRem, 0);
@ -362,4 +344,4 @@ template void LtRtProcessing::Process<int16_t>(const int16_t* input, int16_t* ou
template void LtRtProcessing::Process<int32_t>(const int32_t* input, int32_t* output, int frameCount);
template void LtRtProcessing::Process<float>(const float* input, float* output, int frameCount);
}
} // namespace boo

View File

@ -9,19 +9,18 @@
#include "ipp.h"
#endif
namespace boo
{
namespace boo {
#if INTEL_IPP
#define USE_LPF 0
#if USE_LPF
class FIRFilter12k
{
class FIRFilter12k {
IppsFIRSpec_32f* m_firSpec;
Ipp8u* m_firBuffer;
Ipp32f* m_dlySrc;
Ipp32f* m_inBuf;
public:
explicit FIRFilter12k(int windowFrames, double sampleRate);
~FIRFilter12k();
@ -29,8 +28,7 @@ public:
};
#endif
class WindowedHilbert
{
class WindowedHilbert {
#if USE_LPF
FIRFilter12k m_fir;
#endif
@ -43,6 +41,7 @@ class WindowedHilbert
Ipp32fc* m_output[4];
Ipp32f* m_hammingTable;
void _AddWindow();
public:
explicit WindowedHilbert(int windowFrames, double sampleRate);
~WindowedHilbert();
@ -54,8 +53,7 @@ public:
};
#endif
class LtRtProcessing
{
class LtRtProcessing {
AudioVoiceEngineMixInfo m_inMixInfo;
int m_windowFrames;
int m_halfFrames;
@ -68,8 +66,11 @@ class LtRtProcessing
#if INTEL_IPP
WindowedHilbert m_hilbertSL, m_hilbertSR;
#endif
template <typename T> T* _getInBuf();
template <typename T> T* _getOutBuf();
template <typename T>
T* _getInBuf();
template <typename T>
T* _getOutBuf();
public:
LtRtProcessing(int _5msFrames, const AudioVoiceEngineMixInfo& mixInfo);
template <typename T>
@ -77,5 +78,4 @@ public:
const AudioVoiceEngineMixInfo& inMixInfo() const { return m_inMixInfo; }
};
}
} // namespace boo

View File

@ -1,12 +1,11 @@
#include "MIDICommon.hpp"
#include "boo/audiodev/IMIDIPort.hpp"
namespace boo
{
namespace boo {
IMIDIPort::~IMIDIPort() {}
IMIDIIn::~IMIDIIn() {}
IMIDIOut::~IMIDIOut() {}
IMIDIInOut::~IMIDIInOut() {}
}
} // namespace boo

View File

@ -1,10 +1,8 @@
#pragma once
namespace boo
{
namespace boo {
enum class Status
{
enum class Status {
NoteOff = 0x80,
NoteOn = 0x90,
NotePressure = 0xA0,
@ -27,4 +25,3 @@ enum class Status
};
}

View File

@ -3,28 +3,23 @@
#include <memory>
#include <algorithm>
namespace boo
{
namespace boo {
static inline uint8_t clamp7(uint8_t val) { return std::max(0, std::min(127, int(val))); }
bool MIDIDecoder::_readContinuedValue(std::vector<uint8_t>::const_iterator& it,
std::vector<uint8_t>::const_iterator end,
uint32_t& valOut)
{
std::vector<uint8_t>::const_iterator end, uint32_t& valOut) {
uint8_t a = *it++;
valOut = a & 0x7f;
if (a & 0x80)
{
if (a & 0x80) {
if (it == end)
return false;
valOut <<= 7;
a = *it++;
valOut |= a & 0x7f;
if (a & 0x80)
{
if (a & 0x80) {
if (it == end)
return false;
valOut <<= 7;
@ -36,13 +31,10 @@ bool MIDIDecoder::_readContinuedValue(std::vector<uint8_t>::const_iterator& it,
return true;
}
std::vector<uint8_t>::const_iterator
MIDIDecoder::receiveBytes(std::vector<uint8_t>::const_iterator begin,
std::vector<uint8_t>::const_iterator end)
{
std::vector<uint8_t>::const_iterator MIDIDecoder::receiveBytes(std::vector<uint8_t>::const_iterator begin,
std::vector<uint8_t>::const_iterator end) {
std::vector<uint8_t>::const_iterator it = begin;
while (it != end)
{
while (it != end) {
uint8_t a = *it++;
uint8_t b;
if (a & 0x80)
@ -50,8 +42,7 @@ MIDIDecoder::receiveBytes(std::vector<uint8_t>::const_iterator begin,
else
it--;
if (m_status == 0xff)
{
if (m_status == 0xff) {
/* Meta events (ignored for now) */
if (it == end)
return begin;
@ -60,13 +51,10 @@ MIDIDecoder::receiveBytes(std::vector<uint8_t>::const_iterator begin,
uint32_t length;
_readContinuedValue(it, end, length);
it += length;
} else
{
} else {
uint8_t chan = m_status & 0xf;
switch (Status(m_status & 0xf0))
{
case Status::NoteOff:
{
switch (Status(m_status & 0xf0)) {
case Status::NoteOff: {
if (it == end)
return begin;
a = *it++;
@ -76,8 +64,7 @@ MIDIDecoder::receiveBytes(std::vector<uint8_t>::const_iterator begin,
m_out.noteOff(chan, clamp7(a), clamp7(b));
break;
}
case Status::NoteOn:
{
case Status::NoteOn: {
if (it == end)
return begin;
a = *it++;
@ -87,8 +74,7 @@ MIDIDecoder::receiveBytes(std::vector<uint8_t>::const_iterator begin,
m_out.noteOn(chan, clamp7(a), clamp7(b));
break;
}
case Status::NotePressure:
{
case Status::NotePressure: {
if (it == end)
return begin;
a = *it++;
@ -98,8 +84,7 @@ MIDIDecoder::receiveBytes(std::vector<uint8_t>::const_iterator begin,
m_out.notePressure(chan, clamp7(a), clamp7(b));
break;
}
case Status::ControlChange:
{
case Status::ControlChange: {
if (it == end)
return begin;
a = *it++;
@ -109,24 +94,21 @@ MIDIDecoder::receiveBytes(std::vector<uint8_t>::const_iterator begin,
m_out.controlChange(chan, clamp7(a), clamp7(b));
break;
}
case Status::ProgramChange:
{
case Status::ProgramChange: {
if (it == end)
return begin;
a = *it++;
m_out.programChange(chan, clamp7(a));
break;
}
case Status::ChannelPressure:
{
case Status::ChannelPressure: {
if (it == end)
return begin;
a = *it++;
m_out.channelPressure(chan, clamp7(a));
break;
}
case Status::PitchBend:
{
case Status::PitchBend: {
if (it == end)
return begin;
a = *it++;
@ -136,28 +118,23 @@ MIDIDecoder::receiveBytes(std::vector<uint8_t>::const_iterator begin,
m_out.pitchBend(chan, clamp7(b) * 128 + clamp7(a));
break;
}
case Status::SysEx:
{
switch (Status(m_status & 0xff))
{
case Status::SysEx:
{
case Status::SysEx: {
switch (Status(m_status & 0xff)) {
case Status::SysEx: {
uint32_t len;
if (!_readContinuedValue(it, end, len) || end - it < len)
return begin;
m_out.sysex(&*it, len);
break;
}
case Status::TimecodeQuarterFrame:
{
case Status::TimecodeQuarterFrame: {
if (it == end)
return begin;
a = *it++;
m_out.timeCodeQuarterFrame(a >> 4 & 0x7, a & 0xf);
break;
}
case Status::SongPositionPointer:
{
case Status::SongPositionPointer: {
if (it == end)
return begin;
a = *it++;
@ -167,8 +144,7 @@ MIDIDecoder::receiveBytes(std::vector<uint8_t>::const_iterator begin,
m_out.songPositionPointer(clamp7(b) * 128 + clamp7(a));
break;
}
case Status::SongSelect:
{
case Status::SongSelect: {
if (it == end)
return begin;
a = *it++;
@ -206,4 +182,4 @@ MIDIDecoder::receiveBytes(std::vector<uint8_t>::const_iterator begin,
return it;
}
}
} // namespace boo

View File

@ -1,16 +1,13 @@
#include "boo/audiodev/MIDIEncoder.hpp"
#include "MIDICommon.hpp"
namespace boo
{
namespace boo {
template <class Sender>
void MIDIEncoder<Sender>::_sendMessage(const uint8_t* data, size_t len)
{
void MIDIEncoder<Sender>::_sendMessage(const uint8_t* data, size_t len) {
if (data[0] == m_status)
m_sender.send(data + 1, len - 1);
else
{
else {
if (data[0] & 0x80)
m_status = data[0];
m_sender.send(data, len);
@ -18,20 +15,17 @@ void MIDIEncoder<Sender>::_sendMessage(const uint8_t* data, size_t len)
}
template <class Sender>
void MIDIEncoder<Sender>::_sendContinuedValue(uint32_t val)
{
void MIDIEncoder<Sender>::_sendContinuedValue(uint32_t val) {
uint8_t send[3] = {};
uint8_t* ptr = nullptr;
if (val >= 0x4000)
{
if (val >= 0x4000) {
ptr = &send[0];
send[0] = 0x80 | ((val / 0x4000) & 0x7f);
send[1] = 0x80;
val &= 0x3fff;
}
if (val >= 0x80)
{
if (val >= 0x80) {
if (!ptr)
ptr = &send[1];
send[1] = 0x80 | ((val / 0x80) & 0x7f);
@ -45,114 +39,86 @@ void MIDIEncoder<Sender>::_sendContinuedValue(uint32_t val)
}
template <class Sender>
void MIDIEncoder<Sender>::noteOff(uint8_t chan, uint8_t key, uint8_t velocity)
{
uint8_t cmd[3] = {uint8_t(int(Status::NoteOff) | (chan & 0xf)),
uint8_t(key & 0x7f), uint8_t(velocity & 0x7f)};
void MIDIEncoder<Sender>::noteOff(uint8_t chan, uint8_t key, uint8_t velocity) {
uint8_t cmd[3] = {uint8_t(int(Status::NoteOff) | (chan & 0xf)), uint8_t(key & 0x7f), uint8_t(velocity & 0x7f)};
_sendMessage(cmd, 3);
}
template <class Sender>
void MIDIEncoder<Sender>::noteOn(uint8_t chan, uint8_t key, uint8_t velocity)
{
uint8_t cmd[3] = {uint8_t(int(Status::NoteOn) | (chan & 0xf)),
uint8_t(key & 0x7f), uint8_t(velocity & 0x7f)};
void MIDIEncoder<Sender>::noteOn(uint8_t chan, uint8_t key, uint8_t velocity) {
uint8_t cmd[3] = {uint8_t(int(Status::NoteOn) | (chan & 0xf)), uint8_t(key & 0x7f), uint8_t(velocity & 0x7f)};
_sendMessage(cmd, 3);
}
template <class Sender>
void MIDIEncoder<Sender>::notePressure(uint8_t chan, uint8_t key, uint8_t pressure)
{
uint8_t cmd[3] = {uint8_t(int(Status::NotePressure) | (chan & 0xf)),
uint8_t(key & 0x7f), uint8_t(pressure & 0x7f)};
void MIDIEncoder<Sender>::notePressure(uint8_t chan, uint8_t key, uint8_t pressure) {
uint8_t cmd[3] = {uint8_t(int(Status::NotePressure) | (chan & 0xf)), uint8_t(key & 0x7f), uint8_t(pressure & 0x7f)};
_sendMessage(cmd, 3);
}
template <class Sender>
void MIDIEncoder<Sender>::controlChange(uint8_t chan, uint8_t control, uint8_t value)
{
uint8_t cmd[3] = {uint8_t(int(Status::ControlChange) | (chan & 0xf)),
uint8_t(control & 0x7f), uint8_t(value & 0x7f)};
void MIDIEncoder<Sender>::controlChange(uint8_t chan, uint8_t control, uint8_t value) {
uint8_t cmd[3] = {uint8_t(int(Status::ControlChange) | (chan & 0xf)), uint8_t(control & 0x7f), uint8_t(value & 0x7f)};
_sendMessage(cmd, 3);
}
template <class Sender>
void MIDIEncoder<Sender>::programChange(uint8_t chan, uint8_t program)
{
uint8_t cmd[2] = {uint8_t(int(Status::ProgramChange) | (chan & 0xf)),
uint8_t(program & 0x7f)};
void MIDIEncoder<Sender>::programChange(uint8_t chan, uint8_t program) {
uint8_t cmd[2] = {uint8_t(int(Status::ProgramChange) | (chan & 0xf)), uint8_t(program & 0x7f)};
_sendMessage(cmd, 2);
}
template <class Sender>
void MIDIEncoder<Sender>::channelPressure(uint8_t chan, uint8_t pressure)
{
uint8_t cmd[2] = {uint8_t(int(Status::ChannelPressure) | (chan & 0xf)),
uint8_t(pressure & 0x7f)};
void MIDIEncoder<Sender>::channelPressure(uint8_t chan, uint8_t pressure) {
uint8_t cmd[2] = {uint8_t(int(Status::ChannelPressure) | (chan & 0xf)), uint8_t(pressure & 0x7f)};
_sendMessage(cmd, 2);
}
template <class Sender>
void MIDIEncoder<Sender>::pitchBend(uint8_t chan, int16_t pitch)
{
uint8_t cmd[3] = {uint8_t(int(Status::PitchBend) | (chan & 0xf)),
uint8_t((pitch % 128) & 0x7f), uint8_t((pitch / 128) & 0x7f)};
_sendMessage(cmd, 3);
}
template <class Sender>
void MIDIEncoder<Sender>::allSoundOff(uint8_t chan)
{
uint8_t cmd[3] = {uint8_t(int(Status::ControlChange) | (chan & 0xf)),
120, 0};
void MIDIEncoder<Sender>::pitchBend(uint8_t chan, int16_t pitch) {
uint8_t cmd[3] = {uint8_t(int(Status::PitchBend) | (chan & 0xf)), uint8_t((pitch % 128) & 0x7f),
uint8_t((pitch / 128) & 0x7f)};
_sendMessage(cmd, 3);
}
template <class Sender>
void MIDIEncoder<Sender>::resetAllControllers(uint8_t chan)
{
uint8_t cmd[3] = {uint8_t(int(Status::ControlChange) | (chan & 0xf)),
121, 0};
void MIDIEncoder<Sender>::allSoundOff(uint8_t chan) {
uint8_t cmd[3] = {uint8_t(int(Status::ControlChange) | (chan & 0xf)), 120, 0};
_sendMessage(cmd, 3);
}
template <class Sender>
void MIDIEncoder<Sender>::localControl(uint8_t chan, bool on)
{
uint8_t cmd[3] = {uint8_t(int(Status::ControlChange) | (chan & 0xf)),
122, uint8_t(on ? 127 : 0)};
void MIDIEncoder<Sender>::resetAllControllers(uint8_t chan) {
uint8_t cmd[3] = {uint8_t(int(Status::ControlChange) | (chan & 0xf)), 121, 0};
_sendMessage(cmd, 3);
}
template <class Sender>
void MIDIEncoder<Sender>::allNotesOff(uint8_t chan)
{
uint8_t cmd[3] = {uint8_t(int(Status::ControlChange) | (chan & 0xf)),
123, 0};
void MIDIEncoder<Sender>::localControl(uint8_t chan, bool on) {
uint8_t cmd[3] = {uint8_t(int(Status::ControlChange) | (chan & 0xf)), 122, uint8_t(on ? 127 : 0)};
_sendMessage(cmd, 3);
}
template <class Sender>
void MIDIEncoder<Sender>::omniMode(uint8_t chan, bool on)
{
uint8_t cmd[3] = {uint8_t(int(Status::ControlChange) | (chan & 0xf)),
uint8_t(on ? 125 : 124), 0};
void MIDIEncoder<Sender>::allNotesOff(uint8_t chan) {
uint8_t cmd[3] = {uint8_t(int(Status::ControlChange) | (chan & 0xf)), 123, 0};
_sendMessage(cmd, 3);
}
template <class Sender>
void MIDIEncoder<Sender>::polyMode(uint8_t chan, bool on)
{
uint8_t cmd[3] = {uint8_t(int(Status::ControlChange) | (chan & 0xf)),
uint8_t(on ? 127 : 126), 0};
void MIDIEncoder<Sender>::omniMode(uint8_t chan, bool on) {
uint8_t cmd[3] = {uint8_t(int(Status::ControlChange) | (chan & 0xf)), uint8_t(on ? 125 : 124), 0};
_sendMessage(cmd, 3);
}
template <class Sender>
void MIDIEncoder<Sender>::polyMode(uint8_t chan, bool on) {
uint8_t cmd[3] = {uint8_t(int(Status::ControlChange) | (chan & 0xf)), uint8_t(on ? 127 : 126), 0};
_sendMessage(cmd, 3);
}
template <class Sender>
void MIDIEncoder<Sender>::sysex(const void* data, size_t len)
{
void MIDIEncoder<Sender>::sysex(const void* data, size_t len) {
uint8_t cmd = uint8_t(Status::SysEx);
_sendMessage(&cmd, 1);
_sendContinuedValue(len);
@ -162,62 +128,50 @@ void MIDIEncoder<Sender>::sysex(const void* data, size_t len)
}
template <class Sender>
void MIDIEncoder<Sender>::timeCodeQuarterFrame(uint8_t message, uint8_t value)
{
uint8_t cmd[2] = {uint8_t(int(Status::TimecodeQuarterFrame)),
uint8_t((message & 0x7 << 4) | (value & 0xf))};
void MIDIEncoder<Sender>::timeCodeQuarterFrame(uint8_t message, uint8_t value) {
uint8_t cmd[2] = {uint8_t(int(Status::TimecodeQuarterFrame)), uint8_t((message & 0x7 << 4) | (value & 0xf))};
_sendMessage(cmd, 2);
}
template <class Sender>
void MIDIEncoder<Sender>::songPositionPointer(uint16_t pointer)
{
uint8_t cmd[3] = {uint8_t(int(Status::SongPositionPointer)),
uint8_t((pointer % 128) & 0x7f), uint8_t((pointer / 128) & 0x7f)};
void MIDIEncoder<Sender>::songPositionPointer(uint16_t pointer) {
uint8_t cmd[3] = {uint8_t(int(Status::SongPositionPointer)), uint8_t((pointer % 128) & 0x7f),
uint8_t((pointer / 128) & 0x7f)};
_sendMessage(cmd, 3);
}
template <class Sender>
void MIDIEncoder<Sender>::songSelect(uint8_t song)
{
uint8_t cmd[2] = {uint8_t(int(Status::TimecodeQuarterFrame)),
uint8_t(song & 0x7f)};
void MIDIEncoder<Sender>::songSelect(uint8_t song) {
uint8_t cmd[2] = {uint8_t(int(Status::TimecodeQuarterFrame)), uint8_t(song & 0x7f)};
_sendMessage(cmd, 2);
}
template <class Sender>
void MIDIEncoder<Sender>::tuneRequest()
{
void MIDIEncoder<Sender>::tuneRequest() {
uint8_t cmd = uint8_t(Status::TuneRequest);
_sendMessage(&cmd, 1);
}
template <class Sender>
void MIDIEncoder<Sender>::startSeq()
{
void MIDIEncoder<Sender>::startSeq() {
uint8_t cmd = uint8_t(Status::Start);
_sendMessage(&cmd, 1);
}
template <class Sender>
void MIDIEncoder<Sender>::continueSeq()
{
void MIDIEncoder<Sender>::continueSeq() {
uint8_t cmd = uint8_t(Status::Continue);
_sendMessage(&cmd, 1);
}
template <class Sender>
void MIDIEncoder<Sender>::stopSeq()
{
void MIDIEncoder<Sender>::stopSeq() {
uint8_t cmd = uint8_t(Status::Stop);
_sendMessage(&cmd, 1);
}
template <class Sender>
void MIDIEncoder<Sender>::reset()
{
void MIDIEncoder<Sender>::reset() {
uint8_t cmd = uint8_t(Status::Reset);
_sendMessage(&cmd, 1);
}
@ -225,4 +179,4 @@ void MIDIEncoder<Sender>::reset()
template class MIDIEncoder<IMIDIOut>;
template class MIDIEncoder<IMIDIInOut>;
}
} // namespace boo

View File

@ -6,37 +6,25 @@
#include <pulse/pulseaudio.h>
#include <unistd.h>
namespace boo
{
namespace boo {
static logvisor::Module Log("boo::PulseAudio");
logvisor::Module ALSALog("boo::ALSA");
static const uint64_t StereoChans = (1 << PA_CHANNEL_POSITION_FRONT_LEFT) |
(1 << PA_CHANNEL_POSITION_FRONT_RIGHT);
static const uint64_t StereoChans = (1 << PA_CHANNEL_POSITION_FRONT_LEFT) | (1 << PA_CHANNEL_POSITION_FRONT_RIGHT);
static const uint64_t QuadChans = (1 << PA_CHANNEL_POSITION_FRONT_LEFT) |
(1 << PA_CHANNEL_POSITION_FRONT_RIGHT) |
(1 << PA_CHANNEL_POSITION_REAR_LEFT) |
(1 << PA_CHANNEL_POSITION_REAR_RIGHT);
static const uint64_t QuadChans = (1 << PA_CHANNEL_POSITION_FRONT_LEFT) | (1 << PA_CHANNEL_POSITION_FRONT_RIGHT) |
(1 << PA_CHANNEL_POSITION_REAR_LEFT) | (1 << PA_CHANNEL_POSITION_REAR_RIGHT);
static const uint64_t S51Chans = (1 << PA_CHANNEL_POSITION_FRONT_LEFT) |
(1 << PA_CHANNEL_POSITION_FRONT_RIGHT) |
(1 << PA_CHANNEL_POSITION_REAR_LEFT) |
(1 << PA_CHANNEL_POSITION_REAR_RIGHT) |
(1 << PA_CHANNEL_POSITION_FRONT_CENTER) |
(1 << PA_CHANNEL_POSITION_LFE);
static const uint64_t S51Chans = (1 << PA_CHANNEL_POSITION_FRONT_LEFT) | (1 << PA_CHANNEL_POSITION_FRONT_RIGHT) |
(1 << PA_CHANNEL_POSITION_REAR_LEFT) | (1 << PA_CHANNEL_POSITION_REAR_RIGHT) |
(1 << PA_CHANNEL_POSITION_FRONT_CENTER) | (1 << PA_CHANNEL_POSITION_LFE);
static const uint64_t S71Chans = (1 << PA_CHANNEL_POSITION_FRONT_LEFT) |
(1 << PA_CHANNEL_POSITION_FRONT_RIGHT) |
(1 << PA_CHANNEL_POSITION_REAR_LEFT) |
(1 << PA_CHANNEL_POSITION_REAR_RIGHT) |
(1 << PA_CHANNEL_POSITION_FRONT_CENTER) |
(1 << PA_CHANNEL_POSITION_LFE) |
(1 << PA_CHANNEL_POSITION_SIDE_LEFT) |
(1 << PA_CHANNEL_POSITION_SIDE_RIGHT);
static const uint64_t S71Chans = (1 << PA_CHANNEL_POSITION_FRONT_LEFT) | (1 << PA_CHANNEL_POSITION_FRONT_RIGHT) |
(1 << PA_CHANNEL_POSITION_REAR_LEFT) | (1 << PA_CHANNEL_POSITION_REAR_RIGHT) |
(1 << PA_CHANNEL_POSITION_FRONT_CENTER) | (1 << PA_CHANNEL_POSITION_LFE) |
(1 << PA_CHANNEL_POSITION_SIDE_LEFT) | (1 << PA_CHANNEL_POSITION_SIDE_RIGHT);
struct PulseAudioVoiceEngine : LinuxMidi
{
struct PulseAudioVoiceEngine : LinuxMidi {
pa_mainloop* m_mainloop = nullptr;
pa_context* m_ctx = nullptr;
pa_stream* m_stream = nullptr;
@ -45,34 +33,29 @@ struct PulseAudioVoiceEngine : LinuxMidi
pa_sample_spec m_sampleSpec = {};
pa_channel_map m_chanMap = {};
int _paWaitReady()
{
int _paWaitReady() {
int retval = 0;
while (pa_context_get_state(m_ctx) < PA_CONTEXT_READY)
pa_mainloop_iterate(m_mainloop, 1, &retval);
return retval;
}
int _paStreamWaitReady()
{
int _paStreamWaitReady() {
int retval = 0;
while (pa_stream_get_state(m_stream) < PA_STREAM_READY)
pa_mainloop_iterate(m_mainloop, 1, &retval);
return retval;
}
int _paIterate(pa_operation* op) const
{
int _paIterate(pa_operation* op) const {
int retval = 0;
while (pa_operation_get_state(op) == PA_OPERATION_RUNNING)
pa_mainloop_iterate(m_mainloop, 1, &retval);
return retval;
}
bool _setupSink()
{
if (m_stream)
{
bool _setupSink() {
if (m_stream) {
pa_stream_disconnect(m_stream);
pa_stream_unref(m_stream);
m_stream = nullptr;
@ -84,8 +67,7 @@ struct PulseAudioVoiceEngine : LinuxMidi
_paIterate(op);
pa_operation_unref(op);
if (m_sampleSpec.format == PA_SAMPLE_INVALID)
{
if (m_sampleSpec.format == PA_SAMPLE_INVALID) {
Log.report(logvisor::Error, "Unable to setup audio stream");
goto err;
}
@ -96,8 +78,7 @@ struct PulseAudioVoiceEngine : LinuxMidi
m_mixInfo.m_sampleFormat = SOXR_FLOAT32;
m_mixInfo.m_bitsPerSample = 32;
m_mixInfo.m_periodFrames = m_5msFrames;
if (!(m_stream = pa_stream_new(m_ctx, "master", &m_sampleSpec, &m_chanMap)))
{
if (!(m_stream = pa_stream_new(m_ctx, "master", &m_sampleSpec, &m_chanMap))) {
Log.report(logvisor::Error, "Unable to pa_stream_new(): %s", pa_strerror(pa_context_errno(m_ctx)));
goto err;
}
@ -110,9 +91,8 @@ struct PulseAudioVoiceEngine : LinuxMidi
bufAttr.fragsize = UINT32_MAX;
if (pa_stream_connect_playback(m_stream, m_sinkName.c_str(), &bufAttr,
pa_stream_flags_t(PA_STREAM_START_UNMUTED | PA_STREAM_EARLY_REQUESTS),
nullptr, nullptr))
{
pa_stream_flags_t(PA_STREAM_START_UNMUTED | PA_STREAM_EARLY_REQUESTS), nullptr,
nullptr)) {
Log.report(logvisor::Error, "Unable to pa_stream_connect_playback()");
goto err;
}
@ -124,8 +104,7 @@ struct PulseAudioVoiceEngine : LinuxMidi
_resetSampleRate();
return true;
err:
if (m_stream)
{
if (m_stream) {
pa_stream_disconnect(m_stream);
pa_stream_unref(m_stream);
m_stream = nullptr;
@ -133,10 +112,8 @@ struct PulseAudioVoiceEngine : LinuxMidi
return false;
}
PulseAudioVoiceEngine()
{
if (!(m_mainloop = pa_mainloop_new()))
{
PulseAudioVoiceEngine() {
if (!(m_mainloop = pa_mainloop_new())) {
Log.report(logvisor::Error, "Unable to pa_mainloop_new()");
return;
}
@ -147,8 +124,7 @@ struct PulseAudioVoiceEngine : LinuxMidi
char pidStr[16];
snprintf(pidStr, 16, "%d", int(getpid()));
pa_proplist_sets(propList, PA_PROP_APPLICATION_PROCESS_ID, pidStr);
if (!(m_ctx = pa_context_new_with_proplist(mlApi, APP->getFriendlyName().data(), propList)))
{
if (!(m_ctx = pa_context_new_with_proplist(mlApi, APP->getFriendlyName().data(), propList))) {
Log.report(logvisor::Error, "Unable to pa_context_new_with_proplist()");
pa_mainloop_free(m_mainloop);
m_mainloop = nullptr;
@ -157,8 +133,7 @@ struct PulseAudioVoiceEngine : LinuxMidi
pa_operation* op;
if (pa_context_connect(m_ctx, nullptr, PA_CONTEXT_NOFLAGS, nullptr))
{
if (pa_context_connect(m_ctx, nullptr, PA_CONTEXT_NOFLAGS, nullptr)) {
Log.report(logvisor::Error, "Unable to pa_context_connect()");
goto err;
}
@ -181,37 +156,30 @@ struct PulseAudioVoiceEngine : LinuxMidi
m_mainloop = nullptr;
}
~PulseAudioVoiceEngine()
{
if (m_stream)
{
~PulseAudioVoiceEngine() {
if (m_stream) {
pa_stream_disconnect(m_stream);
pa_stream_unref(m_stream);
}
if (m_ctx)
{
if (m_ctx) {
pa_context_disconnect(m_ctx);
pa_context_unref(m_ctx);
}
if (m_mainloop)
{
if (m_mainloop) {
pa_mainloop_free(m_mainloop);
}
}
static void _streamMoved(pa_stream* p, PulseAudioVoiceEngine* userdata)
{
static void _streamMoved(pa_stream* p, PulseAudioVoiceEngine* userdata) {
userdata->m_sinkName = pa_stream_get_device_name(p);
userdata->m_handleMove = true;
}
static void _getServerInfoReply(pa_context* c, const pa_server_info* i, PulseAudioVoiceEngine* userdata)
{
static void _getServerInfoReply(pa_context* c, const pa_server_info* i, PulseAudioVoiceEngine* userdata) {
userdata->m_sinkName = i->default_sink_name;
}
void _parseAudioChannelSet(const pa_channel_map* chm)
{
void _parseAudioChannelSet(const pa_channel_map* chm) {
m_chanMap = *chm;
ChannelMap& chmapOut = m_mixInfo.m_channelMap;
@ -219,11 +187,9 @@ struct PulseAudioVoiceEngine : LinuxMidi
uint64_t chBits = 0;
chmapOut.m_channelCount = chm->channels;
for (unsigned c=0 ; c<chm->channels ; ++c)
{
for (unsigned c = 0; c < chm->channels; ++c) {
chBits |= 1 << chm->map[c];
switch (chm->map[c])
{
switch (chm->map[c]) {
case PA_CHANNEL_POSITION_FRONT_LEFT:
chmapOut.m_channels[c] = AudioChannel::FrontLeft;
break;
@ -254,56 +220,45 @@ struct PulseAudioVoiceEngine : LinuxMidi
}
}
static const std::array<AudioChannelSet, 4> testSets =
{{AudioChannelSet::Surround71, AudioChannelSet::Surround51,
AudioChannelSet::Quad, AudioChannelSet::Stereo}};
for (AudioChannelSet set : testSets)
{
switch (set)
{
case AudioChannelSet::Stereo:
{
if ((chBits & StereoChans) == StereoChans)
{
static const std::array<AudioChannelSet, 4> testSets = {
{AudioChannelSet::Surround71, AudioChannelSet::Surround51, AudioChannelSet::Quad, AudioChannelSet::Stereo}};
for (AudioChannelSet set : testSets) {
switch (set) {
case AudioChannelSet::Stereo: {
if ((chBits & StereoChans) == StereoChans) {
m_mixInfo.m_channels = AudioChannelSet::Stereo;
return;
}
break;
}
case AudioChannelSet::Quad:
{
if ((chBits & QuadChans) == QuadChans)
{
case AudioChannelSet::Quad: {
if ((chBits & QuadChans) == QuadChans) {
m_mixInfo.m_channels = AudioChannelSet::Quad;
return;
}
break;
}
case AudioChannelSet::Surround51:
{
if ((chBits & S51Chans) == S51Chans)
{
case AudioChannelSet::Surround51: {
if ((chBits & S51Chans) == S51Chans) {
m_mixInfo.m_channels = AudioChannelSet::Surround51;
return;
}
break;
}
case AudioChannelSet::Surround71:
{
if ((chBits & S71Chans) == S71Chans)
{
case AudioChannelSet::Surround71: {
if ((chBits & S71Chans) == S71Chans) {
m_mixInfo.m_channels = AudioChannelSet::Surround71;
return;
}
break;
}
default: break;
default:
break;
}
}
}
static void _getSinkInfoReply(pa_context* c, const pa_sink_info* i, int eol, PulseAudioVoiceEngine* userdata)
{
static void _getSinkInfoReply(pa_context* c, const pa_sink_info* i, int eol, PulseAudioVoiceEngine* userdata) {
if (!i)
return;
userdata->m_sampleSpec.format = PA_SAMPLE_FLOAT32;
@ -313,13 +268,11 @@ struct PulseAudioVoiceEngine : LinuxMidi
}
mutable std::vector<std::pair<std::string, std::string>> m_sinks;
static void _getSinkInfoListReply(pa_context* c, const pa_sink_info* i, int eol, PulseAudioVoiceEngine* userdata)
{
static void _getSinkInfoListReply(pa_context* c, const pa_sink_info* i, int eol, PulseAudioVoiceEngine* userdata) {
if (i)
userdata->m_sinks.push_back(std::make_pair(i->name, i->description));
}
std::vector<std::pair<std::string, std::string>> enumerateAudioOutputs() const
{
std::vector<std::pair<std::string, std::string>> enumerateAudioOutputs() const {
pa_operation* op = pa_context_get_sink_info_list(m_ctx, pa_sink_info_cb_t(_getSinkInfoListReply), (void*)this);
_paIterate(op);
pa_operation_unref(op);
@ -328,47 +281,37 @@ struct PulseAudioVoiceEngine : LinuxMidi
return ret;
}
std::string getCurrentAudioOutput() const
{
return m_sinkName;
}
std::string getCurrentAudioOutput() const { return m_sinkName; }
bool m_sinkOk = false;
static void _checkAudioSinkReply(pa_context* c, const pa_sink_info* i, int eol, PulseAudioVoiceEngine* userdata)
{
static void _checkAudioSinkReply(pa_context* c, const pa_sink_info* i, int eol, PulseAudioVoiceEngine* userdata) {
if (i)
userdata->m_sinkOk = true;
}
bool setCurrentAudioOutput(const char* name)
{
bool setCurrentAudioOutput(const char* name) {
m_sinkOk = false;
pa_operation* op;
op = pa_context_get_sink_info_by_name(m_ctx, name, pa_sink_info_cb_t(_checkAudioSinkReply), this);
_paIterate(op);
pa_operation_unref(op);
if (m_sinkOk)
{
if (m_sinkOk) {
m_sinkName = name;
return _setupSink();
}
return false;
}
void _doIterate()
{
void _doIterate() {
int retval;
pa_mainloop_iterate(m_mainloop, 1, &retval);
if (m_handleMove)
{
if (m_handleMove) {
m_handleMove = false;
_setupSink();
}
}
void pumpAndMixVoices()
{
if (!m_stream)
{
void pumpAndMixVoices() {
if (!m_stream) {
/* Dummy pump mode - use failsafe defaults for 1/60sec of samples */
m_mixInfo.m_sampleRate = 32000.0;
m_mixInfo.m_sampleFormat = SOXR_FLOAT32_I;
@ -388,8 +331,7 @@ struct PulseAudioVoiceEngine : LinuxMidi
size_t writableFrames = writableSz / frameSz;
size_t writablePeriods = writableFrames / m_mixInfo.m_periodFrames;
if (!writablePeriods)
{
if (!writablePeriods) {
_doIterate();
return;
}
@ -397,11 +339,9 @@ struct PulseAudioVoiceEngine : LinuxMidi
void* data;
size_t periodSz = m_mixInfo.m_periodFrames * frameSz;
size_t nbytes = writablePeriods * periodSz;
if (pa_stream_begin_write(m_stream, &data, &nbytes))
{
if (pa_stream_begin_write(m_stream, &data, &nbytes)) {
pa_stream_state_t st = pa_stream_get_state(m_stream);
Log.report(logvisor::Error, "Unable to pa_stream_begin_write(): %s %d",
pa_strerror(pa_context_errno(m_ctx)), st);
Log.report(logvisor::Error, "Unable to pa_stream_begin_write(): %s %d", pa_strerror(pa_context_errno(m_ctx)), st);
_doIterate();
return;
}
@ -417,9 +357,6 @@ struct PulseAudioVoiceEngine : LinuxMidi
}
};
std::unique_ptr<IAudioVoiceEngine> NewAudioVoiceEngine()
{
return std::make_unique<PulseAudioVoiceEngine>();
}
std::unique_ptr<IAudioVoiceEngine> NewAudioVoiceEngine() { return std::make_unique<PulseAudioVoiceEngine>(); }
}
} // namespace boo

View File

@ -12,8 +12,9 @@
#ifdef TE_VIRTUAL_MIDI
#include <teVirtualMIDI.h>
typedef LPVM_MIDI_PORT (CALLBACK *pfnvirtualMIDICreatePortEx2)
( LPCWSTR portName, LPVM_MIDI_DATA_CB callback, DWORD_PTR dwCallbackInstance, DWORD maxSysexLength, DWORD flags );
typedef LPVM_MIDI_PORT(CALLBACK* pfnvirtualMIDICreatePortEx2)(LPCWSTR portName, LPVM_MIDI_DATA_CB callback,
DWORD_PTR dwCallbackInstance, DWORD maxSysexLength,
DWORD flags);
typedef void(CALLBACK* pfnvirtualMIDIClosePort)(LPVM_MIDI_PORT midiPort);
typedef BOOL(CALLBACK* pfnvirtualMIDISendData)(LPVM_MIDI_PORT midiPort, LPBYTE midiDataBytes, DWORD length);
typedef LPCWSTR(CALLBACK* pfnvirtualMIDIGetDriverVersion)(PWORD major, PWORD minor, PWORD release, PWORD build);
@ -33,16 +34,16 @@ using namespace Windows::Media::Devices;
const IID IID_IAudioClient = __uuidof(IAudioClient);
const IID IID_IAudioRenderClient = __uuidof(IAudioRenderClient);
namespace boo
{
namespace boo {
static logvisor::Module Log("boo::WASAPI");
#define SAFE_RELEASE(punk) \
if ((punk) != NULL) \
{ (punk)->Release(); (punk) = NULL; }
if ((punk) != NULL) { \
(punk)->Release(); \
(punk) = NULL; \
}
struct WASAPIAudioVoiceEngine : BaseAudioVoiceEngine
{
struct WASAPIAudioVoiceEngine : BaseAudioVoiceEngine {
#if !WINDOWS_STORE
ComPtr<IMMDeviceEnumerator> m_enumerator;
ComPtr<IMMDevice> m_device;
@ -57,57 +58,38 @@ struct WASAPIAudioVoiceEngine : BaseAudioVoiceEngine
std::vector<float> m_5msBuffer;
#if !WINDOWS_STORE
struct NotificationClient final : public IMMNotificationClient
{
struct NotificationClient final : public IMMNotificationClient {
WASAPIAudioVoiceEngine& m_parent;
LONG _cRef;
IMMDeviceEnumerator* _pEnumerator;
NotificationClient(WASAPIAudioVoiceEngine& parent)
: m_parent(parent),
_cRef(1),
_pEnumerator(nullptr)
{}
~NotificationClient()
{
SAFE_RELEASE(_pEnumerator)
}
NotificationClient(WASAPIAudioVoiceEngine& parent) : m_parent(parent), _cRef(1), _pEnumerator(nullptr) {}
~NotificationClient(){SAFE_RELEASE(_pEnumerator)}
// IUnknown methods -- AddRef, Release, and QueryInterface
ULONG STDMETHODCALLTYPE AddRef()
{
ULONG STDMETHODCALLTYPE AddRef() {
return InterlockedIncrement(&_cRef);
}
ULONG STDMETHODCALLTYPE Release()
{
ULONG STDMETHODCALLTYPE Release() {
ULONG ulRef = InterlockedDecrement(&_cRef);
if (0 == ulRef)
{
if (0 == ulRef) {
delete this;
}
return ulRef;
}
HRESULT STDMETHODCALLTYPE QueryInterface(
REFIID riid, VOID **ppvInterface)
{
if (IID_IUnknown == riid)
{
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, VOID** ppvInterface) {
if (IID_IUnknown == riid) {
AddRef();
*ppvInterface = (IUnknown*)this;
}
else if (__uuidof(IMMNotificationClient) == riid)
{
} else if (__uuidof(IMMNotificationClient) == riid) {
AddRef();
*ppvInterface = (IMMNotificationClient*)this;
}
else
{
} else {
*ppvInterface = NULL;
return E_NOINTERFACE;
}
@ -116,55 +98,32 @@ struct WASAPIAudioVoiceEngine : BaseAudioVoiceEngine
// Callback methods for device-event notifications.
HRESULT STDMETHODCALLTYPE OnDefaultDeviceChanged(
EDataFlow flow, ERole role,
LPCWSTR pwstrDeviceId)
{
HRESULT STDMETHODCALLTYPE OnDefaultDeviceChanged(EDataFlow flow, ERole role, LPCWSTR pwstrDeviceId) {
m_parent.m_rebuild = true;
return S_OK;
}
HRESULT STDMETHODCALLTYPE OnDeviceAdded(LPCWSTR pwstrDeviceId)
{
return S_OK;
}
HRESULT STDMETHODCALLTYPE OnDeviceAdded(LPCWSTR pwstrDeviceId) { return S_OK; }
HRESULT STDMETHODCALLTYPE OnDeviceRemoved(LPCWSTR pwstrDeviceId)
{
return S_OK;
}
HRESULT STDMETHODCALLTYPE OnDeviceRemoved(LPCWSTR pwstrDeviceId) { return S_OK; }
HRESULT STDMETHODCALLTYPE OnDeviceStateChanged(
LPCWSTR pwstrDeviceId,
DWORD dwNewState)
{
return S_OK;
}
HRESULT STDMETHODCALLTYPE OnDeviceStateChanged(LPCWSTR pwstrDeviceId, DWORD dwNewState) { return S_OK; }
HRESULT STDMETHODCALLTYPE OnPropertyValueChanged(
LPCWSTR pwstrDeviceId,
const PROPERTYKEY key)
{
return S_OK;
}
HRESULT STDMETHODCALLTYPE OnPropertyValueChanged(LPCWSTR pwstrDeviceId, const PROPERTYKEY key) { return S_OK; }
} m_notificationClient;
#endif
void _buildAudioRenderClient()
{
void _buildAudioRenderClient() {
#if !WINDOWS_STORE
if (!m_device)
{
if (FAILED(m_enumerator->GetDevice(MBSTWCS(m_sinkName.c_str()).c_str(), &m_device)))
{
if (!m_device) {
if (FAILED(m_enumerator->GetDevice(MBSTWCS(m_sinkName.c_str()).c_str(), &m_device))) {
Log.report(logvisor::Error, "unable to obtain audio device %s", m_sinkName.c_str());
m_device.Reset();
return;
}
}
if (FAILED(m_device->Activate(IID_IAudioClient, CLSCTX_ALL, nullptr, &m_audClient)))
{
if (FAILED(m_device->Activate(IID_IAudioClient, CLSCTX_ALL, nullptr, &m_audClient))) {
Log.report(logvisor::Error, L"unable to create audio client from device");
m_device.Reset();
return;
@ -172,8 +131,7 @@ struct WASAPIAudioVoiceEngine : BaseAudioVoiceEngine
#endif
WAVEFORMATEXTENSIBLE* pwfx;
if (FAILED(m_audClient->GetMixFormat((WAVEFORMATEX**)&pwfx)))
{
if (FAILED(m_audClient->GetMixFormat((WAVEFORMATEX**)&pwfx))) {
Log.report(logvisor::Error, L"unable to obtain audio mix format from device");
#if !WINDOWS_STORE
m_device.Reset();
@ -182,17 +140,17 @@ struct WASAPIAudioVoiceEngine : BaseAudioVoiceEngine
}
/* Get channel information */
if ((pwfx->dwChannelMask & (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT)) == (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT))
{
if ((pwfx->dwChannelMask & (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT)) ==
(SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT)) {
m_mixInfo.m_channels = AudioChannelSet::Stereo;
if ((pwfx->dwChannelMask & (SPEAKER_BACK_LEFT|SPEAKER_BACK_RIGHT)) == (SPEAKER_BACK_LEFT|SPEAKER_BACK_RIGHT))
{
if ((pwfx->dwChannelMask & (SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT)) ==
(SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT)) {
m_mixInfo.m_channels = AudioChannelSet::Quad;
if ((pwfx->dwChannelMask & (SPEAKER_FRONT_CENTER|SPEAKER_LOW_FREQUENCY)) == (SPEAKER_FRONT_CENTER|SPEAKER_LOW_FREQUENCY))
{
if ((pwfx->dwChannelMask & (SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY)) ==
(SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY)) {
m_mixInfo.m_channels = AudioChannelSet::Surround51;
if ((pwfx->dwChannelMask & (SPEAKER_SIDE_LEFT|SPEAKER_SIDE_RIGHT)) == (SPEAKER_SIDE_LEFT|SPEAKER_SIDE_RIGHT))
{
if ((pwfx->dwChannelMask & (SPEAKER_SIDE_LEFT | SPEAKER_SIDE_RIGHT)) ==
(SPEAKER_SIDE_LEFT | SPEAKER_SIDE_RIGHT)) {
m_mixInfo.m_channels = AudioChannelSet::Surround71;
}
}
@ -200,8 +158,7 @@ struct WASAPIAudioVoiceEngine : BaseAudioVoiceEngine
}
ChannelMap& chMapOut = m_mixInfo.m_channelMap;
switch (pwfx->Format.nChannels)
{
switch (pwfx->Format.nChannels) {
case 2:
chMapOut.m_channelCount = 2;
chMapOut.m_channels[0] = AudioChannel::FrontLeft;
@ -251,14 +208,8 @@ struct WASAPIAudioVoiceEngine : BaseAudioVoiceEngine
}
/* Initialize audio client */
if (FAILED(m_audClient->Initialize(
AUDCLNT_SHAREMODE_SHARED,
0,
450000, /* 45ms */
0,
(WAVEFORMATEX*)pwfx,
nullptr)))
{
if (FAILED(m_audClient->Initialize(AUDCLNT_SHAREMODE_SHARED, 0, 450000, /* 45ms */
0, (WAVEFORMATEX*)pwfx, nullptr))) {
Log.report(logvisor::Error, L"unable to initialize audio client");
#if !WINDOWS_STORE
m_device.Reset();
@ -272,37 +223,27 @@ struct WASAPIAudioVoiceEngine : BaseAudioVoiceEngine
m_5msBuffer.resize(m_5msFrames * chMapOut.m_channelCount);
if (pwfx->Format.wFormatTag == WAVE_FORMAT_PCM ||
(pwfx->Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE && pwfx->SubFormat == KSDATAFORMAT_SUBTYPE_PCM))
{
if (pwfx->Format.wBitsPerSample == 16)
{
(pwfx->Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE && pwfx->SubFormat == KSDATAFORMAT_SUBTYPE_PCM)) {
if (pwfx->Format.wBitsPerSample == 16) {
m_mixInfo.m_sampleFormat = SOXR_INT16_I;
m_mixInfo.m_bitsPerSample = 16;
}
else if (pwfx->Format.wBitsPerSample == 32)
{
} else if (pwfx->Format.wBitsPerSample == 32) {
m_mixInfo.m_sampleFormat = SOXR_INT32_I;
m_mixInfo.m_bitsPerSample = 32;
}
else
{
} else {
Log.report(logvisor::Fatal, L"unsupported bits-per-sample %d", pwfx->Format.wBitsPerSample);
#if !WINDOWS_STORE
m_device.Reset();
#endif
return;
}
}
else if (pwfx->Format.wFormatTag == WAVE_FORMAT_IEEE_FLOAT ||
(pwfx->Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE && pwfx->SubFormat == KSDATAFORMAT_SUBTYPE_IEEE_FLOAT))
{
if (pwfx->Format.wBitsPerSample == 32)
{
} else if (pwfx->Format.wFormatTag == WAVE_FORMAT_IEEE_FLOAT ||
(pwfx->Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
pwfx->SubFormat == KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)) {
if (pwfx->Format.wBitsPerSample == 32) {
m_mixInfo.m_sampleFormat = SOXR_FLOAT32_I;
m_mixInfo.m_bitsPerSample = 32;
}
else
{
} else {
Log.report(logvisor::Error, L"unsupported floating-point bits-per-sample %d", pwfx->Format.wBitsPerSample);
#if !WINDOWS_STORE
m_device.Reset();
@ -314,8 +255,7 @@ struct WASAPIAudioVoiceEngine : BaseAudioVoiceEngine
CoTaskMemFree(pwfx);
UINT32 bufferFrameCount;
if (FAILED(m_audClient->GetBufferSize(&bufferFrameCount)))
{
if (FAILED(m_audClient->GetBufferSize(&bufferFrameCount))) {
Log.report(logvisor::Error, L"unable to get audio buffer frame count");
#if !WINDOWS_STORE
m_device.Reset();
@ -324,8 +264,7 @@ struct WASAPIAudioVoiceEngine : BaseAudioVoiceEngine
}
m_mixInfo.m_periodFrames = bufferFrameCount;
if (FAILED(m_audClient->GetService(IID_IAudioRenderClient, &m_renderClient)))
{
if (FAILED(m_audClient->GetService(IID_IAudioRenderClient, &m_renderClient))) {
Log.report(logvisor::Error, L"unable to create audio render client");
#if !WINDOWS_STORE
m_device.Reset();
@ -335,55 +274,40 @@ struct WASAPIAudioVoiceEngine : BaseAudioVoiceEngine
}
#if WINDOWS_STORE
struct CompletionHandler : IActivateAudioInterfaceCompletionHandler
{
struct CompletionHandler : IActivateAudioInterfaceCompletionHandler {
WASAPIAudioVoiceEngine& e;
LONG _cRef = 1;
CompletionHandler(WASAPIAudioVoiceEngine& e) : e(e) {}
HRESULT ActivateCompleted(IActivateAudioInterfaceAsyncOperation* operation)
{
HRESULT ActivateCompleted(IActivateAudioInterfaceAsyncOperation* operation) {
return e.ActivateCompleted(operation);
}
ULONG STDMETHODCALLTYPE AddRef()
{
return InterlockedIncrement(&_cRef);
}
ULONG STDMETHODCALLTYPE AddRef() { return InterlockedIncrement(&_cRef); }
ULONG STDMETHODCALLTYPE Release()
{
ULONG STDMETHODCALLTYPE Release() {
ULONG ulRef = InterlockedDecrement(&_cRef);
if (0 == ulRef)
{
if (0 == ulRef) {
delete this;
}
return ulRef;
}
HRESULT STDMETHODCALLTYPE QueryInterface(
REFIID riid, VOID **ppvInterface)
{
if (IID_IUnknown == riid)
{
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, VOID** ppvInterface) {
if (IID_IUnknown == riid) {
AddRef();
*ppvInterface = (IUnknown*)this;
}
else if (__uuidof(IActivateAudioInterfaceCompletionHandler) == riid)
{
} else if (__uuidof(IActivateAudioInterfaceCompletionHandler) == riid) {
AddRef();
*ppvInterface = (IActivateAudioInterfaceCompletionHandler*)this;
}
else
{
} else {
*ppvInterface = NULL;
return E_NOINTERFACE;
}
return S_OK;
}
} m_completion = {*this};
HRESULT ActivateCompleted(IActivateAudioInterfaceAsyncOperation* operation)
{
HRESULT ActivateCompleted(IActivateAudioInterfaceAsyncOperation* operation) {
ComPtr<IUnknown> punkAudioInterface;
HRESULT hrActivateResult;
operation->GetActivateResult(&hrActivateResult, &punkAudioInterface);
@ -402,12 +326,13 @@ struct WASAPIAudioVoiceEngine : BaseAudioVoiceEngine
#if !WINDOWS_STORE
#ifdef TE_VIRTUAL_MIDI
HMODULE virtualMidiModule;
if (!virtualMIDICreatePortEx2PROC && (virtualMidiModule = LoadLibraryW(L"teVirtualMIDI64.dll")))
{
virtualMIDICreatePortEx2PROC = (pfnvirtualMIDICreatePortEx2)GetProcAddress(virtualMidiModule, "virtualMIDICreatePortEx2");
if (!virtualMIDICreatePortEx2PROC && (virtualMidiModule = LoadLibraryW(L"teVirtualMIDI64.dll"))) {
virtualMIDICreatePortEx2PROC =
(pfnvirtualMIDICreatePortEx2)GetProcAddress(virtualMidiModule, "virtualMIDICreatePortEx2");
virtualMIDIClosePortPROC = (pfnvirtualMIDIClosePort)GetProcAddress(virtualMidiModule, "virtualMIDIClosePort");
virtualMIDISendDataPROC = (pfnvirtualMIDISendData)GetProcAddress(virtualMidiModule, "virtualMIDISendData");
virtualMIDIGetDriverVersionPROC = (pfnvirtualMIDIGetDriverVersion)GetProcAddress(virtualMidiModule, "virtualMIDIGetDriverVersion");
virtualMIDIGetDriverVersionPROC =
(pfnvirtualMIDIGetDriverVersion)GetProcAddress(virtualMidiModule, "virtualMIDIGetDriverVersion");
LARGE_INTEGER pf;
QueryPerformanceFrequency(&pf);
PerfFrequency = double(pf.QuadPart);
@ -415,23 +340,19 @@ struct WASAPIAudioVoiceEngine : BaseAudioVoiceEngine
#endif
/* Enumerate default audio device */
if (FAILED(CoCreateInstance(CLSID_MMDeviceEnumerator, nullptr,
CLSCTX_ALL, IID_IMMDeviceEnumerator,
&m_enumerator)))
{
if (FAILED(
CoCreateInstance(CLSID_MMDeviceEnumerator, nullptr, CLSCTX_ALL, IID_IMMDeviceEnumerator, &m_enumerator))) {
Log.report(logvisor::Error, L"unable to create MMDeviceEnumerator instance");
return;
}
if (FAILED(m_enumerator->RegisterEndpointNotificationCallback(&m_notificationClient)))
{
if (FAILED(m_enumerator->RegisterEndpointNotificationCallback(&m_notificationClient))) {
Log.report(logvisor::Error, L"unable to register multimedia event callback");
m_device.Reset();
return;
}
if (FAILED(m_enumerator->GetDefaultAudioEndpoint(eRender, eConsole, &m_device)))
{
if (FAILED(m_enumerator->GetDefaultAudioEndpoint(eRender, eConsole, &m_device))) {
Log.report(logvisor::Error, L"unable to obtain default audio device");
m_device.Reset();
return;
@ -452,8 +373,7 @@ struct WASAPIAudioVoiceEngine : BaseAudioVoiceEngine
bool m_started = false;
bool m_rebuild = false;
void _rebuildAudioRenderClient()
{
void _rebuildAudioRenderClient() {
soxr_datatype_t oldFmt = m_mixInfo.m_sampleFormat;
_buildAudioRenderClient();
@ -466,8 +386,7 @@ struct WASAPIAudioVoiceEngine : BaseAudioVoiceEngine
_resetSampleRate();
}
void pumpAndMixVoices()
{
void pumpAndMixVoices() {
#if WINDOWS_STORE
if (!m_ready)
return;
@ -477,23 +396,19 @@ struct WASAPIAudioVoiceEngine : BaseAudioVoiceEngine
#endif
int attempt = 0;
while (true)
{
while (true) {
if (attempt >= 10)
Log.report(logvisor::Fatal, L"unable to setup AudioRenderClient");
if (m_rebuild)
{
if (m_rebuild) {
m_device.Reset();
_rebuildAudioRenderClient();
}
HRESULT res;
if (!m_started)
{
if (!m_started) {
res = m_audClient->Start();
if (FAILED(res))
{
if (FAILED(res)) {
m_rebuild = true;
++attempt;
continue;
@ -503,8 +418,7 @@ struct WASAPIAudioVoiceEngine : BaseAudioVoiceEngine
UINT32 numFramesPadding;
res = m_audClient->GetCurrentPadding(&numFramesPadding);
if (FAILED(res))
{
if (FAILED(res)) {
m_rebuild = true;
++attempt;
continue;
@ -516,24 +430,20 @@ struct WASAPIAudioVoiceEngine : BaseAudioVoiceEngine
BYTE* bufOut;
res = m_renderClient->GetBuffer(frames, &bufOut);
if (FAILED(res))
{
if (FAILED(res)) {
m_rebuild = true;
++attempt;
continue;
}
for (size_t f=0 ; f<frames ;)
{
if (m_curBufFrame == m_5msFrames)
{
for (size_t f = 0; f < frames;) {
if (m_curBufFrame == m_5msFrames) {
_pumpAndMixVoices(m_5msFrames, m_5msBuffer.data());
m_curBufFrame = 0;
}
size_t remRenderFrames = std::min(frames - f, m_5msFrames - m_curBufFrame);
if (remRenderFrames)
{
if (remRenderFrames) {
memmove(reinterpret_cast<float*>(bufOut) + m_mixInfo.m_channelMap.m_channelCount * f,
&m_5msBuffer[m_curBufFrame * m_mixInfo.m_channelMap.m_channelCount],
remRenderFrames * m_mixInfo.m_channelMap.m_channelCount * sizeof(float));
@ -543,8 +453,7 @@ struct WASAPIAudioVoiceEngine : BaseAudioVoiceEngine
}
res = m_renderClient->ReleaseBuffer(frames, 0);
if (FAILED(res))
{
if (FAILED(res)) {
m_rebuild = true;
++attempt;
continue;
@ -554,16 +463,11 @@ struct WASAPIAudioVoiceEngine : BaseAudioVoiceEngine
}
}
std::string getCurrentAudioOutput() const
{
return m_sinkName;
}
std::string getCurrentAudioOutput() const { return m_sinkName; }
bool setCurrentAudioOutput(const char* name)
{
bool setCurrentAudioOutput(const char* name) {
ComPtr<IMMDevice> newDevice;
if (FAILED(m_enumerator->GetDevice(MBSTWCS(name).c_str(), &newDevice)))
{
if (FAILED(m_enumerator->GetDevice(MBSTWCS(name).c_str(), &newDevice))) {
Log.report(logvisor::Error, "unable to obtain audio device %s", name);
return false;
}
@ -573,21 +477,18 @@ struct WASAPIAudioVoiceEngine : BaseAudioVoiceEngine
return true;
}
std::vector<std::pair<std::string, std::string>> enumerateAudioOutputs() const
{
std::vector<std::pair<std::string, std::string>> enumerateAudioOutputs() const {
std::vector<std::pair<std::string, std::string>> ret;
ComPtr<IMMDeviceCollection> collection;
if (FAILED(m_enumerator->EnumAudioEndpoints(eRender, DEVICE_STATE_ACTIVE, &collection)))
{
if (FAILED(m_enumerator->EnumAudioEndpoints(eRender, DEVICE_STATE_ACTIVE, &collection))) {
Log.report(logvisor::Error, L"unable to enumerate audio outputs");
return ret;
}
UINT count = 0;
collection->GetCount(&count);
for (UINT i = 0; i < count; ++i)
{
for (UINT i = 0; i < count; ++i) {
ComPtr<IMMDevice> device;
collection->Item(i, &device);
LPWSTR devName;
@ -606,15 +507,13 @@ struct WASAPIAudioVoiceEngine : BaseAudioVoiceEngine
}
#if !WINDOWS_STORE
std::vector<std::pair<std::string, std::string>> enumerateMIDIInputs() const
{
std::vector<std::pair<std::string, std::string>> enumerateMIDIInputs() const {
std::vector<std::pair<std::string, std::string>> ret;
UINT numInDevices = midiInGetNumDevs();
ret.reserve(numInDevices);
for (UINT i=0 ; i<numInDevices ; ++i)
{
for (UINT i = 0; i < numInDevices; ++i) {
char name[256];
snprintf(name, 256, "in%u", i);
@ -650,8 +549,7 @@ struct WASAPIAudioVoiceEngine : BaseAudioVoiceEngine
return ret;
}
bool supportsVirtualMIDIIn() const
{
bool supportsVirtualMIDIIn() const {
#ifdef TE_VIRTUAL_MIDI
WORD major, minor, release, build;
return virtualMIDIGetDriverVersionPROC &&
@ -662,11 +560,8 @@ struct WASAPIAudioVoiceEngine : BaseAudioVoiceEngine
}
#ifdef TE_VIRTUAL_MIDI
static void CALLBACK VirtualMIDIReceiveProc(LPVM_MIDI_PORT midiPort,
LPBYTE midiDataBytes,
DWORD length,
IMIDIReceiver* dwInstance)
{
static void CALLBACK VirtualMIDIReceiveProc(LPVM_MIDI_PORT midiPort, LPBYTE midiDataBytes, DWORD length,
IMIDIReceiver* dwInstance) {
std::vector<uint8_t> bytes;
bytes.resize(length);
memcpy(&bytes[0], midiDataBytes, length);
@ -680,14 +575,9 @@ struct WASAPIAudioVoiceEngine : BaseAudioVoiceEngine
}
#endif
static void CALLBACK MIDIReceiveProc(HMIDIIN hMidiIn,
UINT wMsg,
IMIDIReceiver* dwInstance,
DWORD_PTR dwParam1,
DWORD_PTR dwParam2)
{
if (wMsg == MIM_DATA)
{
static void CALLBACK MIDIReceiveProc(HMIDIIN hMidiIn, UINT wMsg, IMIDIReceiver* dwInstance, DWORD_PTR dwParam1,
DWORD_PTR dwParam2) {
if (wMsg == MIM_DATA) {
uint8_t(&ptr)[3] = reinterpret_cast<uint8_t(&)[3]>(dwParam1);
std::vector<uint8_t> bytes(std::cbegin(ptr), std::cend(ptr));
dwInstance->m_receiver(std::move(bytes), dwParam2 / 1000.0);
@ -695,84 +585,54 @@ struct WASAPIAudioVoiceEngine : BaseAudioVoiceEngine
}
#ifdef TE_VIRTUAL_MIDI
struct VMIDIIn : public IMIDIIn
{
struct VMIDIIn : public IMIDIIn {
LPVM_MIDI_PORT m_midi = 0;
VMIDIIn(WASAPIAudioVoiceEngine* parent, ReceiveFunctor&& receiver)
: IMIDIIn(parent, true, std::move(receiver)) {}
VMIDIIn(WASAPIAudioVoiceEngine* parent, ReceiveFunctor&& receiver) : IMIDIIn(parent, true, std::move(receiver)) {}
~VMIDIIn()
{
virtualMIDIClosePortPROC(m_midi);
}
~VMIDIIn() { virtualMIDIClosePortPROC(m_midi); }
std::string description() const
{
return "Virtual MIDI-In";
}
std::string description() const { return "Virtual MIDI-In"; }
};
struct VMIDIOut : public IMIDIOut
{
struct VMIDIOut : public IMIDIOut {
LPVM_MIDI_PORT m_midi = 0;
VMIDIOut(WASAPIAudioVoiceEngine* parent) : IMIDIOut(parent, true) {}
~VMIDIOut()
{
virtualMIDIClosePortPROC(m_midi);
}
~VMIDIOut() { virtualMIDIClosePortPROC(m_midi); }
std::string description() const
{
return "Virtual MIDI-Out";
}
std::string description() const { return "Virtual MIDI-Out"; }
size_t send(const void* buf, size_t len) const
{
size_t send(const void* buf, size_t len) const {
return virtualMIDISendDataPROC(m_midi, (LPBYTE)buf, len) ? len : 0;
}
};
struct VMIDIInOut : public IMIDIInOut
{
struct VMIDIInOut : public IMIDIInOut {
LPVM_MIDI_PORT m_midi = 0;
VMIDIInOut(WASAPIAudioVoiceEngine* parent, ReceiveFunctor&& receiver)
: IMIDIInOut(parent, true, std::move(receiver)) {}
~VMIDIInOut()
{
virtualMIDIClosePortPROC(m_midi);
}
~VMIDIInOut() { virtualMIDIClosePortPROC(m_midi); }
std::string description() const
{
return "Virtual MIDI-In/Out";
}
std::string description() const { return "Virtual MIDI-In/Out"; }
size_t send(const void* buf, size_t len) const
{
size_t send(const void* buf, size_t len) const {
return virtualMIDISendDataPROC(m_midi, (LPBYTE)buf, len) ? len : 0;
}
};
#endif
struct MIDIIn : public IMIDIIn
{
struct MIDIIn : public IMIDIIn {
HMIDIIN m_midi = 0;
MIDIIn(WASAPIAudioVoiceEngine* parent, ReceiveFunctor&& receiver)
: IMIDIIn(parent, false, std::move(receiver)) {}
MIDIIn(WASAPIAudioVoiceEngine* parent, ReceiveFunctor&& receiver) : IMIDIIn(parent, false, std::move(receiver)) {}
~MIDIIn()
{
midiInClose(m_midi);
}
~MIDIIn() { midiInClose(m_midi); }
std::string description() const
{
std::string description() const {
UINT id = 0;
midiInGetID(m_midi, &id);
MIDIINCAPS caps;
@ -787,8 +647,7 @@ struct WASAPIAudioVoiceEngine : BaseAudioVoiceEngine
}
};
struct MIDIOut : public IMIDIOut
{
struct MIDIOut : public IMIDIOut {
HMIDIOUT m_midi = 0;
HMIDISTRM m_strm = 0;
uint8_t m_buf[512];
@ -796,8 +655,7 @@ struct WASAPIAudioVoiceEngine : BaseAudioVoiceEngine
MIDIOut(WASAPIAudioVoiceEngine* parent) : IMIDIOut(parent, false) {}
void prepare()
{
void prepare() {
UINT id = 0;
midiOutGetID(m_midi, &id);
@ -808,15 +666,13 @@ struct WASAPIAudioVoiceEngine : BaseAudioVoiceEngine
midiStreamOpen(&m_strm, &id, 1, NULL, NULL, CALLBACK_NULL);
}
~MIDIOut()
{
~MIDIOut() {
midiStreamClose(m_strm);
midiOutUnprepareHeader(m_midi, &m_hdr, sizeof(m_hdr));
midiOutClose(m_midi);
}
std::string description() const
{
std::string description() const {
UINT id = 0;
midiOutGetID(m_midi, &id);
MIDIOUTCAPS caps;
@ -830,8 +686,7 @@ struct WASAPIAudioVoiceEngine : BaseAudioVoiceEngine
#endif
}
size_t send(const void* buf, size_t len) const
{
size_t send(const void* buf, size_t len) const {
memcpy(const_cast<MIDIOut*>(this)->m_buf, buf, std::min(len, size_t(512)));
const_cast<MIDIOut*>(this)->m_hdr.dwBytesRecorded = len;
midiStreamOut(m_strm, LPMIDIHDR(&m_hdr), sizeof(m_hdr));
@ -839,8 +694,7 @@ struct WASAPIAudioVoiceEngine : BaseAudioVoiceEngine
}
};
struct MIDIInOut : public IMIDIInOut
{
struct MIDIInOut : public IMIDIInOut {
HMIDIIN m_midiIn = 0;
HMIDIOUT m_midiOut = 0;
HMIDISTRM m_strm = 0;
@ -850,8 +704,7 @@ struct WASAPIAudioVoiceEngine : BaseAudioVoiceEngine
MIDIInOut(WASAPIAudioVoiceEngine* parent, ReceiveFunctor&& receiver)
: IMIDIInOut(parent, false, std::move(receiver)) {}
void prepare()
{
void prepare() {
UINT id = 0;
midiOutGetID(m_midiOut, &id);
@ -862,16 +715,14 @@ struct WASAPIAudioVoiceEngine : BaseAudioVoiceEngine
midiStreamOpen(&m_strm, &id, 1, NULL, NULL, CALLBACK_NULL);
}
~MIDIInOut()
{
~MIDIInOut() {
midiInClose(m_midiIn);
midiStreamClose(m_strm);
midiOutUnprepareHeader(m_midiOut, &m_hdr, sizeof(m_hdr));
midiOutClose(m_midiOut);
}
std::string description() const
{
std::string description() const {
UINT id = 0;
midiOutGetID(m_midiOut, &id);
MIDIOUTCAPS caps;
@ -885,8 +736,7 @@ struct WASAPIAudioVoiceEngine : BaseAudioVoiceEngine
#endif
}
size_t send(const void* buf, size_t len) const
{
size_t send(const void* buf, size_t len) const {
memcpy(const_cast<uint8_t*>(m_buf), buf, std::min(len, size_t(512)));
const_cast<MIDIHDR&>(m_hdr).dwBytesRecorded = len;
midiStreamOut(m_strm, LPMIDIHDR(&m_hdr), sizeof(m_hdr));
@ -894,8 +744,7 @@ struct WASAPIAudioVoiceEngine : BaseAudioVoiceEngine
}
};
std::unique_ptr<IMIDIIn> newVirtualMIDIIn(ReceiveFunctor&& receiver)
{
std::unique_ptr<IMIDIIn> newVirtualMIDIIn(ReceiveFunctor&& receiver) {
#ifdef TE_VIRTUAL_MIDI
if (!virtualMIDICreatePortEx2PROC)
return {};
@ -917,8 +766,7 @@ struct WASAPIAudioVoiceEngine : BaseAudioVoiceEngine
#endif
}
std::unique_ptr<IMIDIOut> newVirtualMIDIOut()
{
std::unique_ptr<IMIDIOut> newVirtualMIDIOut() {
#ifdef TE_VIRTUAL_MIDI
if (!virtualMIDICreatePortEx2PROC)
return {};
@ -939,8 +787,7 @@ struct WASAPIAudioVoiceEngine : BaseAudioVoiceEngine
#endif
}
std::unique_ptr<IMIDIInOut> newVirtualMIDIInOut(ReceiveFunctor&& receiver)
{
std::unique_ptr<IMIDIInOut> newVirtualMIDIInOut(ReceiveFunctor&& receiver) {
#ifdef TE_VIRTUAL_MIDI
if (!virtualMIDICreatePortEx2PROC)
return {};
@ -950,9 +797,9 @@ struct WASAPIAudioVoiceEngine : BaseAudioVoiceEngine
return {};
SystemString name = SystemString(APP->getFriendlyName()) + _SYS_STR(" MIDI-In/Out");
auto port = virtualMIDICreatePortEx2PROC(name.c_str(), LPVM_MIDI_DATA_CB(VirtualMIDIReceiveProc),
DWORD_PTR(static_cast<IMIDIReceiver*>(ret.get())), 512,
TE_VM_FLAGS_SUPPORTED);
auto port =
virtualMIDICreatePortEx2PROC(name.c_str(), LPVM_MIDI_DATA_CB(VirtualMIDIReceiveProc),
DWORD_PTR(static_cast<IMIDIReceiver*>(ret.get())), 512, TE_VM_FLAGS_SUPPORTED);
if (!port)
return {};
static_cast<VMIDIInOut&>(*ret).m_midi = port;
@ -962,8 +809,7 @@ struct WASAPIAudioVoiceEngine : BaseAudioVoiceEngine
#endif
}
std::unique_ptr<IMIDIIn> newRealMIDIIn(const char* name, ReceiveFunctor&& receiver)
{
std::unique_ptr<IMIDIIn> newRealMIDIIn(const char* name, ReceiveFunctor&& receiver) {
if (strncmp(name, "in", 2))
return {};
long id = strtol(name + 2, nullptr, 10);
@ -980,8 +826,7 @@ struct WASAPIAudioVoiceEngine : BaseAudioVoiceEngine
return ret;
}
std::unique_ptr<IMIDIOut> newRealMIDIOut(const char* name)
{
std::unique_ptr<IMIDIOut> newRealMIDIOut(const char* name) {
if (strncmp(name, "out", 3))
return {};
long id = strtol(name + 3, nullptr, 10);
@ -990,16 +835,14 @@ struct WASAPIAudioVoiceEngine : BaseAudioVoiceEngine
if (!ret)
return {};
if (FAILED(midiOutOpen(&static_cast<MIDIOut&>(*ret).m_midi, id, NULL,
NULL, CALLBACK_NULL)))
if (FAILED(midiOutOpen(&static_cast<MIDIOut&>(*ret).m_midi, id, NULL, NULL, CALLBACK_NULL)))
return {};
static_cast<MIDIOut&>(*ret).prepare();
return ret;
}
std::unique_ptr<IMIDIInOut> newRealMIDIInOut(const char* name, ReceiveFunctor&& receiver)
{
std::unique_ptr<IMIDIInOut> newRealMIDIInOut(const char* name, ReceiveFunctor&& receiver) {
const char* in = strstr(name, "in");
const char* out = strstr(name, "out");
@ -1018,8 +861,7 @@ struct WASAPIAudioVoiceEngine : BaseAudioVoiceEngine
return {};
midiInStart(static_cast<MIDIInOut&>(*ret).m_midiIn);
if (FAILED(midiOutOpen(&static_cast<MIDIInOut&>(*ret).m_midiOut, outId, NULL,
NULL, CALLBACK_NULL)))
if (FAILED(midiOutOpen(&static_cast<MIDIInOut&>(*ret).m_midiOut, outId, NULL, NULL, CALLBACK_NULL)))
return {};
static_cast<MIDIInOut&>(*ret).prepare();
@ -1028,48 +870,24 @@ struct WASAPIAudioVoiceEngine : BaseAudioVoiceEngine
bool useMIDILock() const { return true; }
#else
std::vector<std::pair<std::string, std::string>> enumerateMIDIDevices() const
{
return {};
}
std::vector<std::pair<std::string, std::string>> enumerateMIDIDevices() const { return {}; }
std::unique_ptr<IMIDIIn> newVirtualMIDIIn(ReceiveFunctor&& receiver)
{
return {};
}
std::unique_ptr<IMIDIIn> newVirtualMIDIIn(ReceiveFunctor&& receiver) { return {}; }
std::unique_ptr<IMIDIOut> newVirtualMIDIOut()
{
return {};
}
std::unique_ptr<IMIDIOut> newVirtualMIDIOut() { return {}; }
std::unique_ptr<IMIDIInOut> newVirtualMIDIInOut(ReceiveFunctor&& receiver)
{
return {};
}
std::unique_ptr<IMIDIInOut> newVirtualMIDIInOut(ReceiveFunctor&& receiver) { return {}; }
std::unique_ptr<IMIDIIn> newRealMIDIIn(const char* name, ReceiveFunctor&& receiver)
{
return {};
}
std::unique_ptr<IMIDIIn> newRealMIDIIn(const char* name, ReceiveFunctor&& receiver) { return {}; }
std::unique_ptr<IMIDIOut> newRealMIDIOut(const char* name)
{
return {};
}
std::unique_ptr<IMIDIOut> newRealMIDIOut(const char* name) { return {}; }
std::unique_ptr<IMIDIInOut> newRealMIDIInOut(const char* name, ReceiveFunctor&& receiver)
{
return {};
}
std::unique_ptr<IMIDIInOut> newRealMIDIInOut(const char* name, ReceiveFunctor&& receiver) { return {}; }
bool useMIDILock() const { return false; }
#endif
};
std::unique_ptr<IAudioVoiceEngine> NewAudioVoiceEngine()
{
return std::make_unique<WASAPIAudioVoiceEngine>();
}
std::unique_ptr<IAudioVoiceEngine> NewAudioVoiceEngine() { return std::make_unique<WASAPIAudioVoiceEngine>(); }
}
} // namespace boo

View File

@ -2,101 +2,59 @@
#include "logvisor/logvisor.hpp"
#include "boo/audiodev/IAudioVoiceEngine.hpp"
namespace boo
{
namespace boo {
static logvisor::Module Log("boo::WAVOut");
struct WAVOutVoiceEngine : BaseAudioVoiceEngine
{
struct WAVOutVoiceEngine : BaseAudioVoiceEngine {
std::vector<float> m_interleavedBuf;
AudioChannelSet _getAvailableSet()
{
return AudioChannelSet::Stereo;
}
AudioChannelSet _getAvailableSet() { return AudioChannelSet::Stereo; }
std::string getCurrentAudioOutput() const
{
return "wavout";
}
std::string getCurrentAudioOutput() const { return "wavout"; }
bool setCurrentAudioOutput(const char* name)
{
return false;
}
bool setCurrentAudioOutput(const char* name) { return false; }
std::vector<std::pair<std::string, std::string>> enumerateAudioOutputs() const
{
return {{"wavout", "WAVOut"}};
}
std::vector<std::pair<std::string, std::string>> enumerateAudioOutputs() const { return {{"wavout", "WAVOut"}}; }
std::vector<std::pair<std::string, std::string>> enumerateMIDIInputs() const
{
return {};
}
std::vector<std::pair<std::string, std::string>> enumerateMIDIInputs() const { return {}; }
bool supportsVirtualMIDIIn() const
{
return false;
}
bool supportsVirtualMIDIIn() const { return false; }
ReceiveFunctor* m_midiReceiver = nullptr;
struct MIDIIn : public IMIDIIn
{
struct MIDIIn : public IMIDIIn {
MIDIIn(WAVOutVoiceEngine* parent, bool virt, ReceiveFunctor&& receiver)
: IMIDIIn(parent, virt, std::move(receiver)) {}
std::string description() const
{
return "WAVOut MIDI";
}
std::string description() const { return "WAVOut MIDI"; }
};
std::unique_ptr<IMIDIIn> newVirtualMIDIIn(ReceiveFunctor&& receiver)
{
std::unique_ptr<IMIDIIn> newVirtualMIDIIn(ReceiveFunctor&& receiver) {
std::unique_ptr<IMIDIIn> ret = std::make_unique<MIDIIn>(nullptr, true, std::move(receiver));
m_midiReceiver = &ret->m_receiver;
return ret;
}
std::unique_ptr<IMIDIOut> newVirtualMIDIOut()
{
return {};
}
std::unique_ptr<IMIDIOut> newVirtualMIDIOut() { return {}; }
std::unique_ptr<IMIDIInOut> newVirtualMIDIInOut(ReceiveFunctor&& receiver)
{
return {};
}
std::unique_ptr<IMIDIInOut> newVirtualMIDIInOut(ReceiveFunctor&& receiver) { return {}; }
std::unique_ptr<IMIDIIn> newRealMIDIIn(const char* name, ReceiveFunctor&& receiver)
{
return {};
}
std::unique_ptr<IMIDIIn> newRealMIDIIn(const char* name, ReceiveFunctor&& receiver) { return {}; }
std::unique_ptr<IMIDIOut> newRealMIDIOut(const char* name)
{
return {};
}
std::unique_ptr<IMIDIOut> newRealMIDIOut(const char* name) { return {}; }
std::unique_ptr<IMIDIInOut> newRealMIDIInOut(const char* name, ReceiveFunctor&& receiver)
{
return {};
}
std::unique_ptr<IMIDIInOut> newRealMIDIInOut(const char* name, ReceiveFunctor&& receiver) { return {}; }
bool useMIDILock() const { return false; }
FILE* m_fp = nullptr;
size_t m_bytesWritten = 0;
void prepareWAV(double sampleRate, int numChans)
{
void prepareWAV(double sampleRate, int numChans) {
uint32_t speakerMask = 0;
switch (numChans)
{
switch (numChans) {
default:
case 2:
numChans = 2;
@ -140,12 +98,12 @@ struct WAVOutVoiceEngine : BaseAudioVoiceEngine
m_mixInfo.m_channelMap.m_channels[5] = AudioChannel::RearRight;
m_mixInfo.m_channelMap.m_channels[6] = AudioChannel::SideLeft;
m_mixInfo.m_channelMap.m_channels[7] = AudioChannel::SideRight;
speakerMask = 0x00000001 | 0x00000002 | 0x00000004 | 0x00000008 | 0x00000010 | 0x00000020 | 0x00000200 | 0x00000400;
speakerMask =
0x00000001 | 0x00000002 | 0x00000004 | 0x00000008 | 0x00000010 | 0x00000020 | 0x00000200 | 0x00000400;
break;
}
if (numChans == 2)
{
if (numChans == 2) {
fwrite("RIFF", 1, 4, m_fp);
uint32_t dataSize = 0;
uint32_t chunkSize = 36 + dataSize;
@ -171,9 +129,7 @@ struct WAVOutVoiceEngine : BaseAudioVoiceEngine
fwrite("data", 1, 4, m_fp);
fwrite(&dataSize, 1, 4, m_fp);
}
else
{
} else {
fwrite("RIFF", 1, 4, m_fp);
uint32_t dataSize = 0;
uint32_t chunkSize = 60 + dataSize;
@ -213,8 +169,7 @@ struct WAVOutVoiceEngine : BaseAudioVoiceEngine
_buildAudioRenderClient();
}
WAVOutVoiceEngine(const char* path, double sampleRate, int numChans)
{
WAVOutVoiceEngine(const char* path, double sampleRate, int numChans) {
m_fp = fopen(path, "wb");
if (!m_fp)
return;
@ -222,8 +177,7 @@ struct WAVOutVoiceEngine : BaseAudioVoiceEngine
}
#if _WIN32
WAVOutVoiceEngine(const wchar_t* path, double sampleRate, int numChans)
{
WAVOutVoiceEngine(const wchar_t* path, double sampleRate, int numChans) {
m_fp = _wfopen(path, L"wb");
if (!m_fp)
return;
@ -231,21 +185,17 @@ struct WAVOutVoiceEngine : BaseAudioVoiceEngine
}
#endif
void finishWav()
{
void finishWav() {
uint32_t dataSize = m_bytesWritten;
if (m_mixInfo.m_channelMap.m_channelCount == 2)
{
if (m_mixInfo.m_channelMap.m_channelCount == 2) {
fseek(m_fp, 4, SEEK_SET);
uint32_t chunkSize = 36 + dataSize;
fwrite(&chunkSize, 1, 4, m_fp);
fseek(m_fp, 40, SEEK_SET);
fwrite(&dataSize, 1, 4, m_fp);
}
else
{
} else {
fseek(m_fp, 4, SEEK_SET);
uint32_t chunkSize = 60 + dataSize;
fwrite(&chunkSize, 1, 4, m_fp);
@ -257,27 +207,21 @@ struct WAVOutVoiceEngine : BaseAudioVoiceEngine
fclose(m_fp);
}
~WAVOutVoiceEngine()
{
finishWav();
}
~WAVOutVoiceEngine() { finishWav(); }
void _buildAudioRenderClient()
{
void _buildAudioRenderClient() {
m_5msFrames = m_mixInfo.m_sampleRate * 5 / 1000;
m_interleavedBuf.resize(m_mixInfo.m_channelMap.m_channelCount * m_5msFrames);
}
void _rebuildAudioRenderClient(double sampleRate, size_t periodFrames)
{
void _rebuildAudioRenderClient(double sampleRate, size_t periodFrames) {
m_mixInfo.m_periodFrames = periodFrames;
m_mixInfo.m_sampleRate = sampleRate;
_buildAudioRenderClient();
_resetSampleRate();
}
void pumpAndMixVoices()
{
void pumpAndMixVoices() {
size_t frameSz = 4 * m_mixInfo.m_channelMap.m_channelCount;
_pumpAndMixVoices(m_5msFrames, m_interleavedBuf.data());
fwrite(m_interleavedBuf.data(), 1, m_5msFrames * frameSz, m_fp);
@ -285,8 +229,7 @@ struct WAVOutVoiceEngine : BaseAudioVoiceEngine
}
};
std::unique_ptr<IAudioVoiceEngine> NewWAVAudioVoiceEngine(const char* path, double sampleRate, int numChans)
{
std::unique_ptr<IAudioVoiceEngine> NewWAVAudioVoiceEngine(const char* path, double sampleRate, int numChans) {
std::unique_ptr<IAudioVoiceEngine> ret = std::make_unique<WAVOutVoiceEngine>(path, sampleRate, numChans);
if (!static_cast<WAVOutVoiceEngine&>(*ret).m_fp)
return {};
@ -294,8 +237,7 @@ std::unique_ptr<IAudioVoiceEngine> NewWAVAudioVoiceEngine(const char* path, doub
}
#if _WIN32
std::unique_ptr<IAudioVoiceEngine> NewWAVAudioVoiceEngine(const wchar_t* path, double sampleRate, int numChans)
{
std::unique_ptr<IAudioVoiceEngine> NewWAVAudioVoiceEngine(const wchar_t* path, double sampleRate, int numChans) {
std::unique_ptr<IAudioVoiceEngine> ret = std::make_unique<WAVOutVoiceEngine>(path, sampleRate, numChans);
if (!static_cast<WAVOutVoiceEngine&>(*ret).m_fp)
return {};
@ -303,4 +245,4 @@ std::unique_ptr<IAudioVoiceEngine> NewWAVAudioVoiceEngine(const wchar_t* path, d
}
#endif
}
} // namespace boo

View File

@ -1,18 +1,15 @@
#include "Common.hpp"
#include <cmath>
namespace boo
{
namespace boo {
void UpdateGammaLUT(ITextureD* tex, float gamma)
{
void UpdateGammaLUT(ITextureD* tex, float gamma) {
void* data = tex->map(65536 * 2);
for (int i=0 ; i<65536 ; ++i)
{
for (int i = 0; i < 65536; ++i) {
float level = std::pow(i / 65535.f, gamma);
reinterpret_cast<uint16_t*>(data)[i] = level * 65535.f;
}
tex->unmap();
}
}
} // namespace boo

View File

@ -10,8 +10,7 @@
#include "boo/graphicsdev/IGraphicsDataFactory.hpp"
#include "../Common.hpp"
namespace boo
{
namespace boo {
struct BaseGraphicsData;
struct BaseGraphicsPool;
@ -20,14 +19,12 @@ template<class NodeCls, class DataCls = BaseGraphicsData>
struct GraphicsDataNode;
/** Inherited by data factory implementations to track the head data and pool nodes */
struct GraphicsDataFactoryHead
{
struct GraphicsDataFactoryHead {
std::recursive_mutex m_dataMutex;
BaseGraphicsData* m_dataHead = nullptr;
BaseGraphicsPool* m_poolHead = nullptr;
~GraphicsDataFactoryHead()
{
~GraphicsDataFactoryHead() {
assert(m_dataHead == nullptr && "Dangling graphics data pools detected");
assert(m_poolHead == nullptr && "Dangling graphics data pools detected");
}
@ -36,11 +33,11 @@ struct GraphicsDataFactoryHead
/** Private generalized data container class.
* Keeps head pointers to all graphics objects by type
*/
struct BaseGraphicsData : ListNode<BaseGraphicsData, GraphicsDataFactoryHead*>
{
struct BaseGraphicsData : ListNode<BaseGraphicsData, GraphicsDataFactoryHead*> {
static BaseGraphicsData*& _getHeadPtr(GraphicsDataFactoryHead* head) { return head->m_dataHead; }
static std::unique_lock<std::recursive_mutex> _getHeadLock(GraphicsDataFactoryHead* head)
{ return std::unique_lock<std::recursive_mutex>{head->m_dataMutex}; }
static std::unique_lock<std::recursive_mutex> _getHeadLock(GraphicsDataFactoryHead* head) {
return std::unique_lock<std::recursive_mutex>{head->m_dataMutex};
}
__BooTraceFields
@ -53,85 +50,114 @@ struct BaseGraphicsData : ListNode<BaseGraphicsData, GraphicsDataFactoryHead*>
GraphicsDataNode<ITextureSA, BaseGraphicsData>* m_SATexs = nullptr;
GraphicsDataNode<ITextureD, BaseGraphicsData>* m_DTexs = nullptr;
GraphicsDataNode<ITextureR, BaseGraphicsData>* m_RTexs = nullptr;
template<class T> GraphicsDataNode<T, BaseGraphicsData>*& getHead();
template<class T> size_t countForward()
{ auto* head = getHead<T>(); return head ? head->countForward() : 0; }
std::unique_lock<std::recursive_mutex> destructorLock() override
{ return std::unique_lock<std::recursive_mutex>{m_head->m_dataMutex}; }
template <class T>
GraphicsDataNode<T, BaseGraphicsData>*& getHead();
template <class T>
size_t countForward() {
auto* head = getHead<T>();
return head ? head->countForward() : 0;
}
std::unique_lock<std::recursive_mutex> destructorLock() override {
return std::unique_lock<std::recursive_mutex>{m_head->m_dataMutex};
}
explicit BaseGraphicsData(GraphicsDataFactoryHead& head __BooTraceArgs)
: ListNode<BaseGraphicsData, GraphicsDataFactoryHead*>(&head) __BooTraceInitializer
{}
: ListNode<BaseGraphicsData, GraphicsDataFactoryHead*>(&head) __BooTraceInitializer {}
};
template <> inline GraphicsDataNode<IShaderStage, BaseGraphicsData>*&
BaseGraphicsData::getHead<IShaderStage>() { return m_Ss; }
template <> inline GraphicsDataNode<IShaderPipeline, BaseGraphicsData>*&
BaseGraphicsData::getHead<IShaderPipeline>() { return m_SPs; }
template <> inline GraphicsDataNode<IShaderDataBinding, BaseGraphicsData>*&
BaseGraphicsData::getHead<IShaderDataBinding>() { return m_SBinds; }
template <> inline GraphicsDataNode<IGraphicsBufferS, BaseGraphicsData>*&
BaseGraphicsData::getHead<IGraphicsBufferS>() { return m_SBufs; }
template <> inline GraphicsDataNode<IGraphicsBufferD, BaseGraphicsData>*&
BaseGraphicsData::getHead<IGraphicsBufferD>() { return m_DBufs; }
template <> inline GraphicsDataNode<ITextureS, BaseGraphicsData>*&
BaseGraphicsData::getHead<ITextureS>() { return m_STexs; }
template <> inline GraphicsDataNode<ITextureSA, BaseGraphicsData>*&
BaseGraphicsData::getHead<ITextureSA>() { return m_SATexs; }
template <> inline GraphicsDataNode<ITextureD, BaseGraphicsData>*&
BaseGraphicsData::getHead<ITextureD>() { return m_DTexs; }
template <> inline GraphicsDataNode<ITextureR, BaseGraphicsData>*&
BaseGraphicsData::getHead<ITextureR>() { return m_RTexs; }
template <>
inline GraphicsDataNode<IShaderStage, BaseGraphicsData>*& BaseGraphicsData::getHead<IShaderStage>() {
return m_Ss;
}
template <>
inline GraphicsDataNode<IShaderPipeline, BaseGraphicsData>*& BaseGraphicsData::getHead<IShaderPipeline>() {
return m_SPs;
}
template <>
inline GraphicsDataNode<IShaderDataBinding, BaseGraphicsData>*& BaseGraphicsData::getHead<IShaderDataBinding>() {
return m_SBinds;
}
template <>
inline GraphicsDataNode<IGraphicsBufferS, BaseGraphicsData>*& BaseGraphicsData::getHead<IGraphicsBufferS>() {
return m_SBufs;
}
template <>
inline GraphicsDataNode<IGraphicsBufferD, BaseGraphicsData>*& BaseGraphicsData::getHead<IGraphicsBufferD>() {
return m_DBufs;
}
template <>
inline GraphicsDataNode<ITextureS, BaseGraphicsData>*& BaseGraphicsData::getHead<ITextureS>() {
return m_STexs;
}
template <>
inline GraphicsDataNode<ITextureSA, BaseGraphicsData>*& BaseGraphicsData::getHead<ITextureSA>() {
return m_SATexs;
}
template <>
inline GraphicsDataNode<ITextureD, BaseGraphicsData>*& BaseGraphicsData::getHead<ITextureD>() {
return m_DTexs;
}
template <>
inline GraphicsDataNode<ITextureR, BaseGraphicsData>*& BaseGraphicsData::getHead<ITextureR>() {
return m_RTexs;
}
/** Private generalized pool container class.
* Keeps head pointer to exactly one dynamic buffer while otherwise conforming to BaseGraphicsData
*/
struct BaseGraphicsPool : ListNode<BaseGraphicsPool, GraphicsDataFactoryHead*>
{
struct BaseGraphicsPool : ListNode<BaseGraphicsPool, GraphicsDataFactoryHead*> {
static BaseGraphicsPool*& _getHeadPtr(GraphicsDataFactoryHead* head) { return head->m_poolHead; }
static std::unique_lock<std::recursive_mutex> _getHeadLock(GraphicsDataFactoryHead* head)
{ return std::unique_lock<std::recursive_mutex>{head->m_dataMutex}; }
static std::unique_lock<std::recursive_mutex> _getHeadLock(GraphicsDataFactoryHead* head) {
return std::unique_lock<std::recursive_mutex>{head->m_dataMutex};
}
__BooTraceFields
GraphicsDataNode<IGraphicsBufferD, BaseGraphicsPool>* m_DBufs = nullptr;
template<class T> GraphicsDataNode<T, BaseGraphicsPool>*& getHead();
template<class T> size_t countForward()
{ auto* head = getHead<T>(); return head ? head->countForward() : 0; }
std::unique_lock<std::recursive_mutex> destructorLock() override
{ return std::unique_lock<std::recursive_mutex>{m_head->m_dataMutex}; }
template <class T>
GraphicsDataNode<T, BaseGraphicsPool>*& getHead();
template <class T>
size_t countForward() {
auto* head = getHead<T>();
return head ? head->countForward() : 0;
}
std::unique_lock<std::recursive_mutex> destructorLock() override {
return std::unique_lock<std::recursive_mutex>{m_head->m_dataMutex};
}
explicit BaseGraphicsPool(GraphicsDataFactoryHead& head __BooTraceArgs)
: ListNode<BaseGraphicsPool, GraphicsDataFactoryHead*>(&head) __BooTraceInitializer
{}
: ListNode<BaseGraphicsPool, GraphicsDataFactoryHead*>(&head) __BooTraceInitializer {}
};
template <> inline GraphicsDataNode<IGraphicsBufferD, BaseGraphicsPool>*&
BaseGraphicsPool::getHead<IGraphicsBufferD>() { return m_DBufs; }
template <>
inline GraphicsDataNode<IGraphicsBufferD, BaseGraphicsPool>*& BaseGraphicsPool::getHead<IGraphicsBufferD>() {
return m_DBufs;
}
/** Private generalised graphics object node.
* Keeps a strong reference to the data pool that it's a member of;
* as well as doubly-linked pointers to same-type sibling objects
*/
template <class NodeCls, class DataCls>
struct GraphicsDataNode : ListNode<GraphicsDataNode<NodeCls, DataCls>, ObjToken<DataCls>, NodeCls>
{
struct GraphicsDataNode : ListNode<GraphicsDataNode<NodeCls, DataCls>, ObjToken<DataCls>, NodeCls> {
using base = ListNode<GraphicsDataNode<NodeCls, DataCls>, ObjToken<DataCls>, NodeCls>;
static GraphicsDataNode<NodeCls, DataCls>*& _getHeadPtr(ObjToken<DataCls>& head)
{ return head->template getHead<NodeCls>(); }
static std::unique_lock<std::recursive_mutex> _getHeadLock(ObjToken<DataCls>& head)
{ return std::unique_lock<std::recursive_mutex>{head->m_head->m_dataMutex}; }
static GraphicsDataNode<NodeCls, DataCls>*& _getHeadPtr(ObjToken<DataCls>& head) {
return head->template getHead<NodeCls>();
}
static std::unique_lock<std::recursive_mutex> _getHeadLock(ObjToken<DataCls>& head) {
return std::unique_lock<std::recursive_mutex>{head->m_head->m_dataMutex};
}
std::unique_lock<std::recursive_mutex> destructorLock() override
{ return std::unique_lock<std::recursive_mutex>{base::m_head->m_head->m_dataMutex}; }
std::unique_lock<std::recursive_mutex> destructorLock() override {
return std::unique_lock<std::recursive_mutex>{base::m_head->m_head->m_dataMutex};
}
explicit GraphicsDataNode(const ObjToken<DataCls>& data)
: ListNode<GraphicsDataNode<NodeCls, DataCls>, ObjToken<DataCls>, NodeCls>(data)
{}
: ListNode<GraphicsDataNode<NodeCls, DataCls>, ObjToken<DataCls>, NodeCls>(data) {}
class iterator
{
class iterator {
GraphicsDataNode<NodeCls, DataCls>* m_node;
public:
using iterator_category = std::bidirectional_iterator_tag;
using value_type = NodeCls;
@ -142,15 +168,20 @@ struct GraphicsDataNode : ListNode<GraphicsDataNode<NodeCls, DataCls>, ObjToken<
explicit iterator(GraphicsDataNode<NodeCls, DataCls>* node) : m_node(node) {}
NodeCls& operator*() const { return *m_node; }
bool operator!=(const iterator& other) const { return m_node != other.m_node; }
iterator& operator++() { m_node = m_node->m_next; return *this; }
iterator& operator--() { m_node = m_node->m_prev; return *this; }
iterator& operator++() {
m_node = m_node->m_next;
return *this;
}
iterator& operator--() {
m_node = m_node->m_prev;
return *this;
}
};
iterator begin() { return iterator(this); }
iterator end() { return iterator(nullptr); }
size_t countForward()
{
size_t countForward() {
size_t ret = 0;
for (auto& n : *this)
++ret;
@ -160,5 +191,4 @@ struct GraphicsDataNode : ListNode<GraphicsDataNode<NodeCls, DataCls>, ObjToken<
void UpdateGammaLUT(ITextureD* tex, float gamma);
}
} // namespace boo

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,20 +1,17 @@
#include "boo/graphicsdev/glxew.h"
#include "logvisor/logvisor.hpp"
namespace boo
{
namespace boo {
static logvisor::Module Log("boo::GLX");
void GLXExtensionCheck()
{
void GLXExtensionCheck() {
if (!GLXEW_SGI_video_sync)
Log.report(logvisor::Fatal, "GLX_SGI_video_sync not available");
if (!GLXEW_EXT_swap_control && !GLXEW_MESA_swap_control && !GLXEW_SGI_swap_control)
Log.report(logvisor::Fatal, "swap_control not available");
}
void GLXEnableVSync(Display* disp, GLXWindow drawable)
{
void GLXEnableVSync(Display* disp, GLXWindow drawable) {
if (GLXEW_EXT_swap_control)
glXSwapIntervalEXT(disp, drawable, 1);
else if (GLXEW_MESA_swap_control)
@ -23,4 +20,4 @@ void GLXEnableVSync(Display* disp, GLXWindow drawable)
glXSwapIntervalSGI(1);
}
}
} // namespace boo

File diff suppressed because it is too large Load Diff

View File

@ -184,78 +184,114 @@ PFN_vkCreateDebugReportCallbackEXT CreateDebugReportCallbackEXT;
PFN_vkDestroyDebugReportCallbackEXT DestroyDebugReportCallbackEXT;
PFN_vkDebugReportMessageEXT DebugReportMessageEXT;
void init_dispatch_table_top(PFN_vkGetInstanceProcAddr get_instance_proc_addr)
{
void init_dispatch_table_top(PFN_vkGetInstanceProcAddr get_instance_proc_addr) {
GetInstanceProcAddr = get_instance_proc_addr;
CreateInstance = reinterpret_cast<PFN_vkCreateInstance>(GetInstanceProcAddr(VK_NULL_HANDLE, "vkCreateInstance"));
EnumerateInstanceExtensionProperties = reinterpret_cast<PFN_vkEnumerateInstanceExtensionProperties>(GetInstanceProcAddr(VK_NULL_HANDLE, "vkEnumerateInstanceExtensionProperties"));
EnumerateInstanceLayerProperties = reinterpret_cast<PFN_vkEnumerateInstanceLayerProperties>(GetInstanceProcAddr(VK_NULL_HANDLE, "vkEnumerateInstanceLayerProperties"));
EnumerateInstanceExtensionProperties = reinterpret_cast<PFN_vkEnumerateInstanceExtensionProperties>(
GetInstanceProcAddr(VK_NULL_HANDLE, "vkEnumerateInstanceExtensionProperties"));
EnumerateInstanceLayerProperties = reinterpret_cast<PFN_vkEnumerateInstanceLayerProperties>(
GetInstanceProcAddr(VK_NULL_HANDLE, "vkEnumerateInstanceLayerProperties"));
}
void init_dispatch_table_middle(VkInstance instance, bool include_bottom)
{
GetInstanceProcAddr = reinterpret_cast<PFN_vkGetInstanceProcAddr>(GetInstanceProcAddr(instance, "vkGetInstanceProcAddr"));
void init_dispatch_table_middle(VkInstance instance, bool include_bottom) {
GetInstanceProcAddr =
reinterpret_cast<PFN_vkGetInstanceProcAddr>(GetInstanceProcAddr(instance, "vkGetInstanceProcAddr"));
DestroyInstance = reinterpret_cast<PFN_vkDestroyInstance>(GetInstanceProcAddr(instance, "vkDestroyInstance"));
EnumeratePhysicalDevices = reinterpret_cast<PFN_vkEnumeratePhysicalDevices>(GetInstanceProcAddr(instance, "vkEnumeratePhysicalDevices"));
GetPhysicalDeviceFeatures = reinterpret_cast<PFN_vkGetPhysicalDeviceFeatures>(GetInstanceProcAddr(instance, "vkGetPhysicalDeviceFeatures"));
GetPhysicalDeviceFormatProperties = reinterpret_cast<PFN_vkGetPhysicalDeviceFormatProperties>(GetInstanceProcAddr(instance, "vkGetPhysicalDeviceFormatProperties"));
GetPhysicalDeviceImageFormatProperties = reinterpret_cast<PFN_vkGetPhysicalDeviceImageFormatProperties>(GetInstanceProcAddr(instance, "vkGetPhysicalDeviceImageFormatProperties"));
GetPhysicalDeviceProperties = reinterpret_cast<PFN_vkGetPhysicalDeviceProperties>(GetInstanceProcAddr(instance, "vkGetPhysicalDeviceProperties"));
GetPhysicalDeviceQueueFamilyProperties = reinterpret_cast<PFN_vkGetPhysicalDeviceQueueFamilyProperties>(GetInstanceProcAddr(instance, "vkGetPhysicalDeviceQueueFamilyProperties"));
GetPhysicalDeviceMemoryProperties = reinterpret_cast<PFN_vkGetPhysicalDeviceMemoryProperties>(GetInstanceProcAddr(instance, "vkGetPhysicalDeviceMemoryProperties"));
EnumeratePhysicalDevices =
reinterpret_cast<PFN_vkEnumeratePhysicalDevices>(GetInstanceProcAddr(instance, "vkEnumeratePhysicalDevices"));
GetPhysicalDeviceFeatures =
reinterpret_cast<PFN_vkGetPhysicalDeviceFeatures>(GetInstanceProcAddr(instance, "vkGetPhysicalDeviceFeatures"));
GetPhysicalDeviceFormatProperties = reinterpret_cast<PFN_vkGetPhysicalDeviceFormatProperties>(
GetInstanceProcAddr(instance, "vkGetPhysicalDeviceFormatProperties"));
GetPhysicalDeviceImageFormatProperties = reinterpret_cast<PFN_vkGetPhysicalDeviceImageFormatProperties>(
GetInstanceProcAddr(instance, "vkGetPhysicalDeviceImageFormatProperties"));
GetPhysicalDeviceProperties = reinterpret_cast<PFN_vkGetPhysicalDeviceProperties>(
GetInstanceProcAddr(instance, "vkGetPhysicalDeviceProperties"));
GetPhysicalDeviceQueueFamilyProperties = reinterpret_cast<PFN_vkGetPhysicalDeviceQueueFamilyProperties>(
GetInstanceProcAddr(instance, "vkGetPhysicalDeviceQueueFamilyProperties"));
GetPhysicalDeviceMemoryProperties = reinterpret_cast<PFN_vkGetPhysicalDeviceMemoryProperties>(
GetInstanceProcAddr(instance, "vkGetPhysicalDeviceMemoryProperties"));
CreateDevice = reinterpret_cast<PFN_vkCreateDevice>(GetInstanceProcAddr(instance, "vkCreateDevice"));
EnumerateDeviceExtensionProperties = reinterpret_cast<PFN_vkEnumerateDeviceExtensionProperties>(GetInstanceProcAddr(instance, "vkEnumerateDeviceExtensionProperties"));
GetPhysicalDeviceSparseImageFormatProperties = reinterpret_cast<PFN_vkGetPhysicalDeviceSparseImageFormatProperties>(GetInstanceProcAddr(instance, "vkGetPhysicalDeviceSparseImageFormatProperties"));
EnumerateDeviceExtensionProperties = reinterpret_cast<PFN_vkEnumerateDeviceExtensionProperties>(
GetInstanceProcAddr(instance, "vkEnumerateDeviceExtensionProperties"));
GetPhysicalDeviceSparseImageFormatProperties = reinterpret_cast<PFN_vkGetPhysicalDeviceSparseImageFormatProperties>(
GetInstanceProcAddr(instance, "vkGetPhysicalDeviceSparseImageFormatProperties"));
DestroySurfaceKHR = reinterpret_cast<PFN_vkDestroySurfaceKHR>(GetInstanceProcAddr(instance, "vkDestroySurfaceKHR"));
GetPhysicalDeviceSurfaceSupportKHR = reinterpret_cast<PFN_vkGetPhysicalDeviceSurfaceSupportKHR>(GetInstanceProcAddr(instance, "vkGetPhysicalDeviceSurfaceSupportKHR"));
GetPhysicalDeviceSurfaceCapabilitiesKHR = reinterpret_cast<PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR>(GetInstanceProcAddr(instance, "vkGetPhysicalDeviceSurfaceCapabilitiesKHR"));
GetPhysicalDeviceSurfaceFormatsKHR = reinterpret_cast<PFN_vkGetPhysicalDeviceSurfaceFormatsKHR>(GetInstanceProcAddr(instance, "vkGetPhysicalDeviceSurfaceFormatsKHR"));
GetPhysicalDeviceSurfacePresentModesKHR = reinterpret_cast<PFN_vkGetPhysicalDeviceSurfacePresentModesKHR>(GetInstanceProcAddr(instance, "vkGetPhysicalDeviceSurfacePresentModesKHR"));
GetPhysicalDeviceDisplayPropertiesKHR = reinterpret_cast<PFN_vkGetPhysicalDeviceDisplayPropertiesKHR>(GetInstanceProcAddr(instance, "vkGetPhysicalDeviceDisplayPropertiesKHR"));
GetPhysicalDeviceDisplayPlanePropertiesKHR = reinterpret_cast<PFN_vkGetPhysicalDeviceDisplayPlanePropertiesKHR>(GetInstanceProcAddr(instance, "vkGetPhysicalDeviceDisplayPlanePropertiesKHR"));
GetDisplayPlaneSupportedDisplaysKHR = reinterpret_cast<PFN_vkGetDisplayPlaneSupportedDisplaysKHR>(GetInstanceProcAddr(instance, "vkGetDisplayPlaneSupportedDisplaysKHR"));
GetDisplayModePropertiesKHR = reinterpret_cast<PFN_vkGetDisplayModePropertiesKHR>(GetInstanceProcAddr(instance, "vkGetDisplayModePropertiesKHR"));
CreateDisplayModeKHR = reinterpret_cast<PFN_vkCreateDisplayModeKHR>(GetInstanceProcAddr(instance, "vkCreateDisplayModeKHR"));
GetDisplayPlaneCapabilitiesKHR = reinterpret_cast<PFN_vkGetDisplayPlaneCapabilitiesKHR>(GetInstanceProcAddr(instance, "vkGetDisplayPlaneCapabilitiesKHR"));
CreateDisplayPlaneSurfaceKHR = reinterpret_cast<PFN_vkCreateDisplayPlaneSurfaceKHR>(GetInstanceProcAddr(instance, "vkCreateDisplayPlaneSurfaceKHR"));
GetPhysicalDeviceSurfaceSupportKHR = reinterpret_cast<PFN_vkGetPhysicalDeviceSurfaceSupportKHR>(
GetInstanceProcAddr(instance, "vkGetPhysicalDeviceSurfaceSupportKHR"));
GetPhysicalDeviceSurfaceCapabilitiesKHR = reinterpret_cast<PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR>(
GetInstanceProcAddr(instance, "vkGetPhysicalDeviceSurfaceCapabilitiesKHR"));
GetPhysicalDeviceSurfaceFormatsKHR = reinterpret_cast<PFN_vkGetPhysicalDeviceSurfaceFormatsKHR>(
GetInstanceProcAddr(instance, "vkGetPhysicalDeviceSurfaceFormatsKHR"));
GetPhysicalDeviceSurfacePresentModesKHR = reinterpret_cast<PFN_vkGetPhysicalDeviceSurfacePresentModesKHR>(
GetInstanceProcAddr(instance, "vkGetPhysicalDeviceSurfacePresentModesKHR"));
GetPhysicalDeviceDisplayPropertiesKHR = reinterpret_cast<PFN_vkGetPhysicalDeviceDisplayPropertiesKHR>(
GetInstanceProcAddr(instance, "vkGetPhysicalDeviceDisplayPropertiesKHR"));
GetPhysicalDeviceDisplayPlanePropertiesKHR = reinterpret_cast<PFN_vkGetPhysicalDeviceDisplayPlanePropertiesKHR>(
GetInstanceProcAddr(instance, "vkGetPhysicalDeviceDisplayPlanePropertiesKHR"));
GetDisplayPlaneSupportedDisplaysKHR = reinterpret_cast<PFN_vkGetDisplayPlaneSupportedDisplaysKHR>(
GetInstanceProcAddr(instance, "vkGetDisplayPlaneSupportedDisplaysKHR"));
GetDisplayModePropertiesKHR = reinterpret_cast<PFN_vkGetDisplayModePropertiesKHR>(
GetInstanceProcAddr(instance, "vkGetDisplayModePropertiesKHR"));
CreateDisplayModeKHR =
reinterpret_cast<PFN_vkCreateDisplayModeKHR>(GetInstanceProcAddr(instance, "vkCreateDisplayModeKHR"));
GetDisplayPlaneCapabilitiesKHR = reinterpret_cast<PFN_vkGetDisplayPlaneCapabilitiesKHR>(
GetInstanceProcAddr(instance, "vkGetDisplayPlaneCapabilitiesKHR"));
CreateDisplayPlaneSurfaceKHR = reinterpret_cast<PFN_vkCreateDisplayPlaneSurfaceKHR>(
GetInstanceProcAddr(instance, "vkCreateDisplayPlaneSurfaceKHR"));
#ifdef VK_USE_PLATFORM_XLIB_KHR
CreateXlibSurfaceKHR = reinterpret_cast<PFN_vkCreateXlibSurfaceKHR>(GetInstanceProcAddr(instance, "vkCreateXlibSurfaceKHR"));
CreateXlibSurfaceKHR =
reinterpret_cast<PFN_vkCreateXlibSurfaceKHR>(GetInstanceProcAddr(instance, "vkCreateXlibSurfaceKHR"));
#endif
#ifdef VK_USE_PLATFORM_XLIB_KHR
GetPhysicalDeviceXlibPresentationSupportKHR = reinterpret_cast<PFN_vkGetPhysicalDeviceXlibPresentationSupportKHR>(GetInstanceProcAddr(instance, "vkGetPhysicalDeviceXlibPresentationSupportKHR"));
GetPhysicalDeviceXlibPresentationSupportKHR = reinterpret_cast<PFN_vkGetPhysicalDeviceXlibPresentationSupportKHR>(
GetInstanceProcAddr(instance, "vkGetPhysicalDeviceXlibPresentationSupportKHR"));
#endif
#ifdef VK_USE_PLATFORM_XCB_KHR
CreateXcbSurfaceKHR = reinterpret_cast<PFN_vkCreateXcbSurfaceKHR>(GetInstanceProcAddr(instance, "vkCreateXcbSurfaceKHR"));
CreateXcbSurfaceKHR =
reinterpret_cast<PFN_vkCreateXcbSurfaceKHR>(GetInstanceProcAddr(instance, "vkCreateXcbSurfaceKHR"));
#endif
#ifdef VK_USE_PLATFORM_XCB_KHR
GetPhysicalDeviceXcbPresentationSupportKHR = reinterpret_cast<PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR>(GetInstanceProcAddr(instance, "vkGetPhysicalDeviceXcbPresentationSupportKHR"));
GetPhysicalDeviceXcbPresentationSupportKHR = reinterpret_cast<PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR>(
GetInstanceProcAddr(instance, "vkGetPhysicalDeviceXcbPresentationSupportKHR"));
#endif
#ifdef VK_USE_PLATFORM_WAYLAND_KHR
CreateWaylandSurfaceKHR = reinterpret_cast<PFN_vkCreateWaylandSurfaceKHR>(GetInstanceProcAddr(instance, "vkCreateWaylandSurfaceKHR"));
CreateWaylandSurfaceKHR =
reinterpret_cast<PFN_vkCreateWaylandSurfaceKHR>(GetInstanceProcAddr(instance, "vkCreateWaylandSurfaceKHR"));
#endif
#ifdef VK_USE_PLATFORM_WAYLAND_KHR
GetPhysicalDeviceWaylandPresentationSupportKHR = reinterpret_cast<PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR>(GetInstanceProcAddr(instance, "vkGetPhysicalDeviceWaylandPresentationSupportKHR"));
GetPhysicalDeviceWaylandPresentationSupportKHR =
reinterpret_cast<PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR>(
GetInstanceProcAddr(instance, "vkGetPhysicalDeviceWaylandPresentationSupportKHR"));
#endif
#ifdef VK_USE_PLATFORM_MIR_KHR
CreateMirSurfaceKHR = reinterpret_cast<PFN_vkCreateMirSurfaceKHR>(GetInstanceProcAddr(instance, "vkCreateMirSurfaceKHR"));
CreateMirSurfaceKHR =
reinterpret_cast<PFN_vkCreateMirSurfaceKHR>(GetInstanceProcAddr(instance, "vkCreateMirSurfaceKHR"));
#endif
#ifdef VK_USE_PLATFORM_MIR_KHR
GetPhysicalDeviceMirPresentationSupportKHR = reinterpret_cast<PFN_vkGetPhysicalDeviceMirPresentationSupportKHR>(GetInstanceProcAddr(instance, "vkGetPhysicalDeviceMirPresentationSupportKHR"));
GetPhysicalDeviceMirPresentationSupportKHR = reinterpret_cast<PFN_vkGetPhysicalDeviceMirPresentationSupportKHR>(
GetInstanceProcAddr(instance, "vkGetPhysicalDeviceMirPresentationSupportKHR"));
#endif
#ifdef VK_USE_PLATFORM_ANDROID_KHR
CreateAndroidSurfaceKHR = reinterpret_cast<PFN_vkCreateAndroidSurfaceKHR>(GetInstanceProcAddr(instance, "vkCreateAndroidSurfaceKHR"));
CreateAndroidSurfaceKHR =
reinterpret_cast<PFN_vkCreateAndroidSurfaceKHR>(GetInstanceProcAddr(instance, "vkCreateAndroidSurfaceKHR"));
#endif
#ifdef VK_USE_PLATFORM_WIN32_KHR
CreateWin32SurfaceKHR = reinterpret_cast<PFN_vkCreateWin32SurfaceKHR>(GetInstanceProcAddr(instance, "vkCreateWin32SurfaceKHR"));
CreateWin32SurfaceKHR =
reinterpret_cast<PFN_vkCreateWin32SurfaceKHR>(GetInstanceProcAddr(instance, "vkCreateWin32SurfaceKHR"));
#endif
#ifdef VK_USE_PLATFORM_WIN32_KHR
GetPhysicalDeviceWin32PresentationSupportKHR = reinterpret_cast<PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR>(GetInstanceProcAddr(instance, "vkGetPhysicalDeviceWin32PresentationSupportKHR"));
GetPhysicalDeviceWin32PresentationSupportKHR = reinterpret_cast<PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR>(
GetInstanceProcAddr(instance, "vkGetPhysicalDeviceWin32PresentationSupportKHR"));
#endif
CreateDebugReportCallbackEXT = reinterpret_cast<PFN_vkCreateDebugReportCallbackEXT>(GetInstanceProcAddr(instance, "vkCreateDebugReportCallbackEXT"));
DestroyDebugReportCallbackEXT = reinterpret_cast<PFN_vkDestroyDebugReportCallbackEXT>(GetInstanceProcAddr(instance, "vkDestroyDebugReportCallbackEXT"));
DebugReportMessageEXT = reinterpret_cast<PFN_vkDebugReportMessageEXT>(GetInstanceProcAddr(instance, "vkDebugReportMessageEXT"));
CreateDebugReportCallbackEXT = reinterpret_cast<PFN_vkCreateDebugReportCallbackEXT>(
GetInstanceProcAddr(instance, "vkCreateDebugReportCallbackEXT"));
DestroyDebugReportCallbackEXT = reinterpret_cast<PFN_vkDestroyDebugReportCallbackEXT>(
GetInstanceProcAddr(instance, "vkDestroyDebugReportCallbackEXT"));
DebugReportMessageEXT =
reinterpret_cast<PFN_vkDebugReportMessageEXT>(GetInstanceProcAddr(instance, "vkDebugReportMessageEXT"));
if (!include_bottom)
return;
@ -270,14 +306,20 @@ void init_dispatch_table_middle(VkInstance instance, bool include_bottom)
FreeMemory = reinterpret_cast<PFN_vkFreeMemory>(GetInstanceProcAddr(instance, "vkFreeMemory"));
MapMemory = reinterpret_cast<PFN_vkMapMemory>(GetInstanceProcAddr(instance, "vkMapMemory"));
UnmapMemory = reinterpret_cast<PFN_vkUnmapMemory>(GetInstanceProcAddr(instance, "vkUnmapMemory"));
FlushMappedMemoryRanges = reinterpret_cast<PFN_vkFlushMappedMemoryRanges>(GetInstanceProcAddr(instance, "vkFlushMappedMemoryRanges"));
InvalidateMappedMemoryRanges = reinterpret_cast<PFN_vkInvalidateMappedMemoryRanges>(GetInstanceProcAddr(instance, "vkInvalidateMappedMemoryRanges"));
GetDeviceMemoryCommitment = reinterpret_cast<PFN_vkGetDeviceMemoryCommitment>(GetInstanceProcAddr(instance, "vkGetDeviceMemoryCommitment"));
FlushMappedMemoryRanges =
reinterpret_cast<PFN_vkFlushMappedMemoryRanges>(GetInstanceProcAddr(instance, "vkFlushMappedMemoryRanges"));
InvalidateMappedMemoryRanges = reinterpret_cast<PFN_vkInvalidateMappedMemoryRanges>(
GetInstanceProcAddr(instance, "vkInvalidateMappedMemoryRanges"));
GetDeviceMemoryCommitment =
reinterpret_cast<PFN_vkGetDeviceMemoryCommitment>(GetInstanceProcAddr(instance, "vkGetDeviceMemoryCommitment"));
BindBufferMemory = reinterpret_cast<PFN_vkBindBufferMemory>(GetInstanceProcAddr(instance, "vkBindBufferMemory"));
BindImageMemory = reinterpret_cast<PFN_vkBindImageMemory>(GetInstanceProcAddr(instance, "vkBindImageMemory"));
GetBufferMemoryRequirements = reinterpret_cast<PFN_vkGetBufferMemoryRequirements>(GetInstanceProcAddr(instance, "vkGetBufferMemoryRequirements"));
GetImageMemoryRequirements = reinterpret_cast<PFN_vkGetImageMemoryRequirements>(GetInstanceProcAddr(instance, "vkGetImageMemoryRequirements"));
GetImageSparseMemoryRequirements = reinterpret_cast<PFN_vkGetImageSparseMemoryRequirements>(GetInstanceProcAddr(instance, "vkGetImageSparseMemoryRequirements"));
GetBufferMemoryRequirements = reinterpret_cast<PFN_vkGetBufferMemoryRequirements>(
GetInstanceProcAddr(instance, "vkGetBufferMemoryRequirements"));
GetImageMemoryRequirements =
reinterpret_cast<PFN_vkGetImageMemoryRequirements>(GetInstanceProcAddr(instance, "vkGetImageMemoryRequirements"));
GetImageSparseMemoryRequirements = reinterpret_cast<PFN_vkGetImageSparseMemoryRequirements>(
GetInstanceProcAddr(instance, "vkGetImageSparseMemoryRequirements"));
QueueBindSparse = reinterpret_cast<PFN_vkQueueBindSparse>(GetInstanceProcAddr(instance, "vkQueueBindSparse"));
CreateFence = reinterpret_cast<PFN_vkCreateFence>(GetInstanceProcAddr(instance, "vkCreateFence"));
DestroyFence = reinterpret_cast<PFN_vkDestroyFence>(GetInstanceProcAddr(instance, "vkDestroyFence"));
@ -293,104 +335,153 @@ void init_dispatch_table_middle(VkInstance instance, bool include_bottom)
ResetEvent = reinterpret_cast<PFN_vkResetEvent>(GetInstanceProcAddr(instance, "vkResetEvent"));
CreateQueryPool = reinterpret_cast<PFN_vkCreateQueryPool>(GetInstanceProcAddr(instance, "vkCreateQueryPool"));
DestroyQueryPool = reinterpret_cast<PFN_vkDestroyQueryPool>(GetInstanceProcAddr(instance, "vkDestroyQueryPool"));
GetQueryPoolResults = reinterpret_cast<PFN_vkGetQueryPoolResults>(GetInstanceProcAddr(instance, "vkGetQueryPoolResults"));
GetQueryPoolResults =
reinterpret_cast<PFN_vkGetQueryPoolResults>(GetInstanceProcAddr(instance, "vkGetQueryPoolResults"));
CreateBuffer = reinterpret_cast<PFN_vkCreateBuffer>(GetInstanceProcAddr(instance, "vkCreateBuffer"));
DestroyBuffer = reinterpret_cast<PFN_vkDestroyBuffer>(GetInstanceProcAddr(instance, "vkDestroyBuffer"));
CreateBufferView = reinterpret_cast<PFN_vkCreateBufferView>(GetInstanceProcAddr(instance, "vkCreateBufferView"));
DestroyBufferView = reinterpret_cast<PFN_vkDestroyBufferView>(GetInstanceProcAddr(instance, "vkDestroyBufferView"));
CreateImage = reinterpret_cast<PFN_vkCreateImage>(GetInstanceProcAddr(instance, "vkCreateImage"));
DestroyImage = reinterpret_cast<PFN_vkDestroyImage>(GetInstanceProcAddr(instance, "vkDestroyImage"));
GetImageSubresourceLayout = reinterpret_cast<PFN_vkGetImageSubresourceLayout>(GetInstanceProcAddr(instance, "vkGetImageSubresourceLayout"));
GetImageSubresourceLayout =
reinterpret_cast<PFN_vkGetImageSubresourceLayout>(GetInstanceProcAddr(instance, "vkGetImageSubresourceLayout"));
CreateImageView = reinterpret_cast<PFN_vkCreateImageView>(GetInstanceProcAddr(instance, "vkCreateImageView"));
DestroyImageView = reinterpret_cast<PFN_vkDestroyImageView>(GetInstanceProcAddr(instance, "vkDestroyImageView"));
CreateShaderModule = reinterpret_cast<PFN_vkCreateShaderModule>(GetInstanceProcAddr(instance, "vkCreateShaderModule"));
DestroyShaderModule = reinterpret_cast<PFN_vkDestroyShaderModule>(GetInstanceProcAddr(instance, "vkDestroyShaderModule"));
CreatePipelineCache = reinterpret_cast<PFN_vkCreatePipelineCache>(GetInstanceProcAddr(instance, "vkCreatePipelineCache"));
DestroyPipelineCache = reinterpret_cast<PFN_vkDestroyPipelineCache>(GetInstanceProcAddr(instance, "vkDestroyPipelineCache"));
GetPipelineCacheData = reinterpret_cast<PFN_vkGetPipelineCacheData>(GetInstanceProcAddr(instance, "vkGetPipelineCacheData"));
MergePipelineCaches = reinterpret_cast<PFN_vkMergePipelineCaches>(GetInstanceProcAddr(instance, "vkMergePipelineCaches"));
CreateGraphicsPipelines = reinterpret_cast<PFN_vkCreateGraphicsPipelines>(GetInstanceProcAddr(instance, "vkCreateGraphicsPipelines"));
CreateComputePipelines = reinterpret_cast<PFN_vkCreateComputePipelines>(GetInstanceProcAddr(instance, "vkCreateComputePipelines"));
CreateShaderModule =
reinterpret_cast<PFN_vkCreateShaderModule>(GetInstanceProcAddr(instance, "vkCreateShaderModule"));
DestroyShaderModule =
reinterpret_cast<PFN_vkDestroyShaderModule>(GetInstanceProcAddr(instance, "vkDestroyShaderModule"));
CreatePipelineCache =
reinterpret_cast<PFN_vkCreatePipelineCache>(GetInstanceProcAddr(instance, "vkCreatePipelineCache"));
DestroyPipelineCache =
reinterpret_cast<PFN_vkDestroyPipelineCache>(GetInstanceProcAddr(instance, "vkDestroyPipelineCache"));
GetPipelineCacheData =
reinterpret_cast<PFN_vkGetPipelineCacheData>(GetInstanceProcAddr(instance, "vkGetPipelineCacheData"));
MergePipelineCaches =
reinterpret_cast<PFN_vkMergePipelineCaches>(GetInstanceProcAddr(instance, "vkMergePipelineCaches"));
CreateGraphicsPipelines =
reinterpret_cast<PFN_vkCreateGraphicsPipelines>(GetInstanceProcAddr(instance, "vkCreateGraphicsPipelines"));
CreateComputePipelines =
reinterpret_cast<PFN_vkCreateComputePipelines>(GetInstanceProcAddr(instance, "vkCreateComputePipelines"));
DestroyPipeline = reinterpret_cast<PFN_vkDestroyPipeline>(GetInstanceProcAddr(instance, "vkDestroyPipeline"));
CreatePipelineLayout = reinterpret_cast<PFN_vkCreatePipelineLayout>(GetInstanceProcAddr(instance, "vkCreatePipelineLayout"));
DestroyPipelineLayout = reinterpret_cast<PFN_vkDestroyPipelineLayout>(GetInstanceProcAddr(instance, "vkDestroyPipelineLayout"));
CreatePipelineLayout =
reinterpret_cast<PFN_vkCreatePipelineLayout>(GetInstanceProcAddr(instance, "vkCreatePipelineLayout"));
DestroyPipelineLayout =
reinterpret_cast<PFN_vkDestroyPipelineLayout>(GetInstanceProcAddr(instance, "vkDestroyPipelineLayout"));
CreateSampler = reinterpret_cast<PFN_vkCreateSampler>(GetInstanceProcAddr(instance, "vkCreateSampler"));
DestroySampler = reinterpret_cast<PFN_vkDestroySampler>(GetInstanceProcAddr(instance, "vkDestroySampler"));
CreateDescriptorSetLayout = reinterpret_cast<PFN_vkCreateDescriptorSetLayout>(GetInstanceProcAddr(instance, "vkCreateDescriptorSetLayout"));
DestroyDescriptorSetLayout = reinterpret_cast<PFN_vkDestroyDescriptorSetLayout>(GetInstanceProcAddr(instance, "vkDestroyDescriptorSetLayout"));
CreateDescriptorPool = reinterpret_cast<PFN_vkCreateDescriptorPool>(GetInstanceProcAddr(instance, "vkCreateDescriptorPool"));
DestroyDescriptorPool = reinterpret_cast<PFN_vkDestroyDescriptorPool>(GetInstanceProcAddr(instance, "vkDestroyDescriptorPool"));
ResetDescriptorPool = reinterpret_cast<PFN_vkResetDescriptorPool>(GetInstanceProcAddr(instance, "vkResetDescriptorPool"));
AllocateDescriptorSets = reinterpret_cast<PFN_vkAllocateDescriptorSets>(GetInstanceProcAddr(instance, "vkAllocateDescriptorSets"));
FreeDescriptorSets = reinterpret_cast<PFN_vkFreeDescriptorSets>(GetInstanceProcAddr(instance, "vkFreeDescriptorSets"));
UpdateDescriptorSets = reinterpret_cast<PFN_vkUpdateDescriptorSets>(GetInstanceProcAddr(instance, "vkUpdateDescriptorSets"));
CreateDescriptorSetLayout =
reinterpret_cast<PFN_vkCreateDescriptorSetLayout>(GetInstanceProcAddr(instance, "vkCreateDescriptorSetLayout"));
DestroyDescriptorSetLayout =
reinterpret_cast<PFN_vkDestroyDescriptorSetLayout>(GetInstanceProcAddr(instance, "vkDestroyDescriptorSetLayout"));
CreateDescriptorPool =
reinterpret_cast<PFN_vkCreateDescriptorPool>(GetInstanceProcAddr(instance, "vkCreateDescriptorPool"));
DestroyDescriptorPool =
reinterpret_cast<PFN_vkDestroyDescriptorPool>(GetInstanceProcAddr(instance, "vkDestroyDescriptorPool"));
ResetDescriptorPool =
reinterpret_cast<PFN_vkResetDescriptorPool>(GetInstanceProcAddr(instance, "vkResetDescriptorPool"));
AllocateDescriptorSets =
reinterpret_cast<PFN_vkAllocateDescriptorSets>(GetInstanceProcAddr(instance, "vkAllocateDescriptorSets"));
FreeDescriptorSets =
reinterpret_cast<PFN_vkFreeDescriptorSets>(GetInstanceProcAddr(instance, "vkFreeDescriptorSets"));
UpdateDescriptorSets =
reinterpret_cast<PFN_vkUpdateDescriptorSets>(GetInstanceProcAddr(instance, "vkUpdateDescriptorSets"));
CreateFramebuffer = reinterpret_cast<PFN_vkCreateFramebuffer>(GetInstanceProcAddr(instance, "vkCreateFramebuffer"));
DestroyFramebuffer = reinterpret_cast<PFN_vkDestroyFramebuffer>(GetInstanceProcAddr(instance, "vkDestroyFramebuffer"));
DestroyFramebuffer =
reinterpret_cast<PFN_vkDestroyFramebuffer>(GetInstanceProcAddr(instance, "vkDestroyFramebuffer"));
CreateRenderPass = reinterpret_cast<PFN_vkCreateRenderPass>(GetInstanceProcAddr(instance, "vkCreateRenderPass"));
DestroyRenderPass = reinterpret_cast<PFN_vkDestroyRenderPass>(GetInstanceProcAddr(instance, "vkDestroyRenderPass"));
GetRenderAreaGranularity = reinterpret_cast<PFN_vkGetRenderAreaGranularity>(GetInstanceProcAddr(instance, "vkGetRenderAreaGranularity"));
GetRenderAreaGranularity =
reinterpret_cast<PFN_vkGetRenderAreaGranularity>(GetInstanceProcAddr(instance, "vkGetRenderAreaGranularity"));
CreateCommandPool = reinterpret_cast<PFN_vkCreateCommandPool>(GetInstanceProcAddr(instance, "vkCreateCommandPool"));
DestroyCommandPool = reinterpret_cast<PFN_vkDestroyCommandPool>(GetInstanceProcAddr(instance, "vkDestroyCommandPool"));
DestroyCommandPool =
reinterpret_cast<PFN_vkDestroyCommandPool>(GetInstanceProcAddr(instance, "vkDestroyCommandPool"));
ResetCommandPool = reinterpret_cast<PFN_vkResetCommandPool>(GetInstanceProcAddr(instance, "vkResetCommandPool"));
AllocateCommandBuffers = reinterpret_cast<PFN_vkAllocateCommandBuffers>(GetInstanceProcAddr(instance, "vkAllocateCommandBuffers"));
FreeCommandBuffers = reinterpret_cast<PFN_vkFreeCommandBuffers>(GetInstanceProcAddr(instance, "vkFreeCommandBuffers"));
BeginCommandBuffer = reinterpret_cast<PFN_vkBeginCommandBuffer>(GetInstanceProcAddr(instance, "vkBeginCommandBuffer"));
AllocateCommandBuffers =
reinterpret_cast<PFN_vkAllocateCommandBuffers>(GetInstanceProcAddr(instance, "vkAllocateCommandBuffers"));
FreeCommandBuffers =
reinterpret_cast<PFN_vkFreeCommandBuffers>(GetInstanceProcAddr(instance, "vkFreeCommandBuffers"));
BeginCommandBuffer =
reinterpret_cast<PFN_vkBeginCommandBuffer>(GetInstanceProcAddr(instance, "vkBeginCommandBuffer"));
EndCommandBuffer = reinterpret_cast<PFN_vkEndCommandBuffer>(GetInstanceProcAddr(instance, "vkEndCommandBuffer"));
ResetCommandBuffer = reinterpret_cast<PFN_vkResetCommandBuffer>(GetInstanceProcAddr(instance, "vkResetCommandBuffer"));
ResetCommandBuffer =
reinterpret_cast<PFN_vkResetCommandBuffer>(GetInstanceProcAddr(instance, "vkResetCommandBuffer"));
CmdBindPipeline = reinterpret_cast<PFN_vkCmdBindPipeline>(GetInstanceProcAddr(instance, "vkCmdBindPipeline"));
CmdSetViewport = reinterpret_cast<PFN_vkCmdSetViewport>(GetInstanceProcAddr(instance, "vkCmdSetViewport"));
CmdSetScissor = reinterpret_cast<PFN_vkCmdSetScissor>(GetInstanceProcAddr(instance, "vkCmdSetScissor"));
CmdSetLineWidth = reinterpret_cast<PFN_vkCmdSetLineWidth>(GetInstanceProcAddr(instance, "vkCmdSetLineWidth"));
CmdSetDepthBias = reinterpret_cast<PFN_vkCmdSetDepthBias>(GetInstanceProcAddr(instance, "vkCmdSetDepthBias"));
CmdSetBlendConstants = reinterpret_cast<PFN_vkCmdSetBlendConstants>(GetInstanceProcAddr(instance, "vkCmdSetBlendConstants"));
CmdSetBlendConstants =
reinterpret_cast<PFN_vkCmdSetBlendConstants>(GetInstanceProcAddr(instance, "vkCmdSetBlendConstants"));
CmdSetDepthBounds = reinterpret_cast<PFN_vkCmdSetDepthBounds>(GetInstanceProcAddr(instance, "vkCmdSetDepthBounds"));
CmdSetStencilCompareMask = reinterpret_cast<PFN_vkCmdSetStencilCompareMask>(GetInstanceProcAddr(instance, "vkCmdSetStencilCompareMask"));
CmdSetStencilWriteMask = reinterpret_cast<PFN_vkCmdSetStencilWriteMask>(GetInstanceProcAddr(instance, "vkCmdSetStencilWriteMask"));
CmdSetStencilReference = reinterpret_cast<PFN_vkCmdSetStencilReference>(GetInstanceProcAddr(instance, "vkCmdSetStencilReference"));
CmdBindDescriptorSets = reinterpret_cast<PFN_vkCmdBindDescriptorSets>(GetInstanceProcAddr(instance, "vkCmdBindDescriptorSets"));
CmdBindIndexBuffer = reinterpret_cast<PFN_vkCmdBindIndexBuffer>(GetInstanceProcAddr(instance, "vkCmdBindIndexBuffer"));
CmdBindVertexBuffers = reinterpret_cast<PFN_vkCmdBindVertexBuffers>(GetInstanceProcAddr(instance, "vkCmdBindVertexBuffers"));
CmdSetStencilCompareMask =
reinterpret_cast<PFN_vkCmdSetStencilCompareMask>(GetInstanceProcAddr(instance, "vkCmdSetStencilCompareMask"));
CmdSetStencilWriteMask =
reinterpret_cast<PFN_vkCmdSetStencilWriteMask>(GetInstanceProcAddr(instance, "vkCmdSetStencilWriteMask"));
CmdSetStencilReference =
reinterpret_cast<PFN_vkCmdSetStencilReference>(GetInstanceProcAddr(instance, "vkCmdSetStencilReference"));
CmdBindDescriptorSets =
reinterpret_cast<PFN_vkCmdBindDescriptorSets>(GetInstanceProcAddr(instance, "vkCmdBindDescriptorSets"));
CmdBindIndexBuffer =
reinterpret_cast<PFN_vkCmdBindIndexBuffer>(GetInstanceProcAddr(instance, "vkCmdBindIndexBuffer"));
CmdBindVertexBuffers =
reinterpret_cast<PFN_vkCmdBindVertexBuffers>(GetInstanceProcAddr(instance, "vkCmdBindVertexBuffers"));
CmdDraw = reinterpret_cast<PFN_vkCmdDraw>(GetInstanceProcAddr(instance, "vkCmdDraw"));
CmdDrawIndexed = reinterpret_cast<PFN_vkCmdDrawIndexed>(GetInstanceProcAddr(instance, "vkCmdDrawIndexed"));
CmdDrawIndirect = reinterpret_cast<PFN_vkCmdDrawIndirect>(GetInstanceProcAddr(instance, "vkCmdDrawIndirect"));
CmdDrawIndexedIndirect = reinterpret_cast<PFN_vkCmdDrawIndexedIndirect>(GetInstanceProcAddr(instance, "vkCmdDrawIndexedIndirect"));
CmdDrawIndexedIndirect =
reinterpret_cast<PFN_vkCmdDrawIndexedIndirect>(GetInstanceProcAddr(instance, "vkCmdDrawIndexedIndirect"));
CmdDispatch = reinterpret_cast<PFN_vkCmdDispatch>(GetInstanceProcAddr(instance, "vkCmdDispatch"));
CmdDispatchIndirect = reinterpret_cast<PFN_vkCmdDispatchIndirect>(GetInstanceProcAddr(instance, "vkCmdDispatchIndirect"));
CmdDispatchIndirect =
reinterpret_cast<PFN_vkCmdDispatchIndirect>(GetInstanceProcAddr(instance, "vkCmdDispatchIndirect"));
CmdCopyBuffer = reinterpret_cast<PFN_vkCmdCopyBuffer>(GetInstanceProcAddr(instance, "vkCmdCopyBuffer"));
CmdCopyImage = reinterpret_cast<PFN_vkCmdCopyImage>(GetInstanceProcAddr(instance, "vkCmdCopyImage"));
CmdBlitImage = reinterpret_cast<PFN_vkCmdBlitImage>(GetInstanceProcAddr(instance, "vkCmdBlitImage"));
CmdCopyBufferToImage = reinterpret_cast<PFN_vkCmdCopyBufferToImage>(GetInstanceProcAddr(instance, "vkCmdCopyBufferToImage"));
CmdCopyImageToBuffer = reinterpret_cast<PFN_vkCmdCopyImageToBuffer>(GetInstanceProcAddr(instance, "vkCmdCopyImageToBuffer"));
CmdCopyBufferToImage =
reinterpret_cast<PFN_vkCmdCopyBufferToImage>(GetInstanceProcAddr(instance, "vkCmdCopyBufferToImage"));
CmdCopyImageToBuffer =
reinterpret_cast<PFN_vkCmdCopyImageToBuffer>(GetInstanceProcAddr(instance, "vkCmdCopyImageToBuffer"));
CmdUpdateBuffer = reinterpret_cast<PFN_vkCmdUpdateBuffer>(GetInstanceProcAddr(instance, "vkCmdUpdateBuffer"));
CmdFillBuffer = reinterpret_cast<PFN_vkCmdFillBuffer>(GetInstanceProcAddr(instance, "vkCmdFillBuffer"));
CmdClearColorImage = reinterpret_cast<PFN_vkCmdClearColorImage>(GetInstanceProcAddr(instance, "vkCmdClearColorImage"));
CmdClearDepthStencilImage = reinterpret_cast<PFN_vkCmdClearDepthStencilImage>(GetInstanceProcAddr(instance, "vkCmdClearDepthStencilImage"));
CmdClearAttachments = reinterpret_cast<PFN_vkCmdClearAttachments>(GetInstanceProcAddr(instance, "vkCmdClearAttachments"));
CmdClearColorImage =
reinterpret_cast<PFN_vkCmdClearColorImage>(GetInstanceProcAddr(instance, "vkCmdClearColorImage"));
CmdClearDepthStencilImage =
reinterpret_cast<PFN_vkCmdClearDepthStencilImage>(GetInstanceProcAddr(instance, "vkCmdClearDepthStencilImage"));
CmdClearAttachments =
reinterpret_cast<PFN_vkCmdClearAttachments>(GetInstanceProcAddr(instance, "vkCmdClearAttachments"));
CmdResolveImage = reinterpret_cast<PFN_vkCmdResolveImage>(GetInstanceProcAddr(instance, "vkCmdResolveImage"));
CmdSetEvent = reinterpret_cast<PFN_vkCmdSetEvent>(GetInstanceProcAddr(instance, "vkCmdSetEvent"));
CmdResetEvent = reinterpret_cast<PFN_vkCmdResetEvent>(GetInstanceProcAddr(instance, "vkCmdResetEvent"));
CmdWaitEvents = reinterpret_cast<PFN_vkCmdWaitEvents>(GetInstanceProcAddr(instance, "vkCmdWaitEvents"));
CmdPipelineBarrier = reinterpret_cast<PFN_vkCmdPipelineBarrier>(GetInstanceProcAddr(instance, "vkCmdPipelineBarrier"));
CmdPipelineBarrier =
reinterpret_cast<PFN_vkCmdPipelineBarrier>(GetInstanceProcAddr(instance, "vkCmdPipelineBarrier"));
CmdBeginQuery = reinterpret_cast<PFN_vkCmdBeginQuery>(GetInstanceProcAddr(instance, "vkCmdBeginQuery"));
CmdEndQuery = reinterpret_cast<PFN_vkCmdEndQuery>(GetInstanceProcAddr(instance, "vkCmdEndQuery"));
CmdResetQueryPool = reinterpret_cast<PFN_vkCmdResetQueryPool>(GetInstanceProcAddr(instance, "vkCmdResetQueryPool"));
CmdWriteTimestamp = reinterpret_cast<PFN_vkCmdWriteTimestamp>(GetInstanceProcAddr(instance, "vkCmdWriteTimestamp"));
CmdCopyQueryPoolResults = reinterpret_cast<PFN_vkCmdCopyQueryPoolResults>(GetInstanceProcAddr(instance, "vkCmdCopyQueryPoolResults"));
CmdCopyQueryPoolResults =
reinterpret_cast<PFN_vkCmdCopyQueryPoolResults>(GetInstanceProcAddr(instance, "vkCmdCopyQueryPoolResults"));
CmdPushConstants = reinterpret_cast<PFN_vkCmdPushConstants>(GetInstanceProcAddr(instance, "vkCmdPushConstants"));
CmdBeginRenderPass = reinterpret_cast<PFN_vkCmdBeginRenderPass>(GetInstanceProcAddr(instance, "vkCmdBeginRenderPass"));
CmdBeginRenderPass =
reinterpret_cast<PFN_vkCmdBeginRenderPass>(GetInstanceProcAddr(instance, "vkCmdBeginRenderPass"));
CmdNextSubpass = reinterpret_cast<PFN_vkCmdNextSubpass>(GetInstanceProcAddr(instance, "vkCmdNextSubpass"));
CmdEndRenderPass = reinterpret_cast<PFN_vkCmdEndRenderPass>(GetInstanceProcAddr(instance, "vkCmdEndRenderPass"));
CmdExecuteCommands = reinterpret_cast<PFN_vkCmdExecuteCommands>(GetInstanceProcAddr(instance, "vkCmdExecuteCommands"));
CreateSwapchainKHR = reinterpret_cast<PFN_vkCreateSwapchainKHR>(GetInstanceProcAddr(instance, "vkCreateSwapchainKHR"));
DestroySwapchainKHR = reinterpret_cast<PFN_vkDestroySwapchainKHR>(GetInstanceProcAddr(instance, "vkDestroySwapchainKHR"));
GetSwapchainImagesKHR = reinterpret_cast<PFN_vkGetSwapchainImagesKHR>(GetInstanceProcAddr(instance, "vkGetSwapchainImagesKHR"));
AcquireNextImageKHR = reinterpret_cast<PFN_vkAcquireNextImageKHR>(GetInstanceProcAddr(instance, "vkAcquireNextImageKHR"));
CmdExecuteCommands =
reinterpret_cast<PFN_vkCmdExecuteCommands>(GetInstanceProcAddr(instance, "vkCmdExecuteCommands"));
CreateSwapchainKHR =
reinterpret_cast<PFN_vkCreateSwapchainKHR>(GetInstanceProcAddr(instance, "vkCreateSwapchainKHR"));
DestroySwapchainKHR =
reinterpret_cast<PFN_vkDestroySwapchainKHR>(GetInstanceProcAddr(instance, "vkDestroySwapchainKHR"));
GetSwapchainImagesKHR =
reinterpret_cast<PFN_vkGetSwapchainImagesKHR>(GetInstanceProcAddr(instance, "vkGetSwapchainImagesKHR"));
AcquireNextImageKHR =
reinterpret_cast<PFN_vkAcquireNextImageKHR>(GetInstanceProcAddr(instance, "vkAcquireNextImageKHR"));
QueuePresentKHR = reinterpret_cast<PFN_vkQueuePresentKHR>(GetInstanceProcAddr(instance, "vkQueuePresentKHR"));
CreateSharedSwapchainsKHR = reinterpret_cast<PFN_vkCreateSharedSwapchainsKHR>(GetInstanceProcAddr(instance, "vkCreateSharedSwapchainsKHR"));
CreateSharedSwapchainsKHR =
reinterpret_cast<PFN_vkCreateSharedSwapchainsKHR>(GetInstanceProcAddr(instance, "vkCreateSharedSwapchainsKHR"));
}
void init_dispatch_table_bottom(VkInstance instance, VkDevice dev)
{
void init_dispatch_table_bottom(VkInstance instance, VkDevice dev) {
GetDeviceProcAddr = reinterpret_cast<PFN_vkGetDeviceProcAddr>(GetInstanceProcAddr(instance, "vkGetDeviceProcAddr"));
GetDeviceProcAddr = reinterpret_cast<PFN_vkGetDeviceProcAddr>(GetDeviceProcAddr(dev, "vkGetDeviceProcAddr"));
@ -403,14 +494,20 @@ void init_dispatch_table_bottom(VkInstance instance, VkDevice dev)
FreeMemory = reinterpret_cast<PFN_vkFreeMemory>(GetDeviceProcAddr(dev, "vkFreeMemory"));
MapMemory = reinterpret_cast<PFN_vkMapMemory>(GetDeviceProcAddr(dev, "vkMapMemory"));
UnmapMemory = reinterpret_cast<PFN_vkUnmapMemory>(GetDeviceProcAddr(dev, "vkUnmapMemory"));
FlushMappedMemoryRanges = reinterpret_cast<PFN_vkFlushMappedMemoryRanges>(GetDeviceProcAddr(dev, "vkFlushMappedMemoryRanges"));
InvalidateMappedMemoryRanges = reinterpret_cast<PFN_vkInvalidateMappedMemoryRanges>(GetDeviceProcAddr(dev, "vkInvalidateMappedMemoryRanges"));
GetDeviceMemoryCommitment = reinterpret_cast<PFN_vkGetDeviceMemoryCommitment>(GetDeviceProcAddr(dev, "vkGetDeviceMemoryCommitment"));
FlushMappedMemoryRanges =
reinterpret_cast<PFN_vkFlushMappedMemoryRanges>(GetDeviceProcAddr(dev, "vkFlushMappedMemoryRanges"));
InvalidateMappedMemoryRanges =
reinterpret_cast<PFN_vkInvalidateMappedMemoryRanges>(GetDeviceProcAddr(dev, "vkInvalidateMappedMemoryRanges"));
GetDeviceMemoryCommitment =
reinterpret_cast<PFN_vkGetDeviceMemoryCommitment>(GetDeviceProcAddr(dev, "vkGetDeviceMemoryCommitment"));
BindBufferMemory = reinterpret_cast<PFN_vkBindBufferMemory>(GetDeviceProcAddr(dev, "vkBindBufferMemory"));
BindImageMemory = reinterpret_cast<PFN_vkBindImageMemory>(GetDeviceProcAddr(dev, "vkBindImageMemory"));
GetBufferMemoryRequirements = reinterpret_cast<PFN_vkGetBufferMemoryRequirements>(GetDeviceProcAddr(dev, "vkGetBufferMemoryRequirements"));
GetImageMemoryRequirements = reinterpret_cast<PFN_vkGetImageMemoryRequirements>(GetDeviceProcAddr(dev, "vkGetImageMemoryRequirements"));
GetImageSparseMemoryRequirements = reinterpret_cast<PFN_vkGetImageSparseMemoryRequirements>(GetDeviceProcAddr(dev, "vkGetImageSparseMemoryRequirements"));
GetBufferMemoryRequirements =
reinterpret_cast<PFN_vkGetBufferMemoryRequirements>(GetDeviceProcAddr(dev, "vkGetBufferMemoryRequirements"));
GetImageMemoryRequirements =
reinterpret_cast<PFN_vkGetImageMemoryRequirements>(GetDeviceProcAddr(dev, "vkGetImageMemoryRequirements"));
GetImageSparseMemoryRequirements = reinterpret_cast<PFN_vkGetImageSparseMemoryRequirements>(
GetDeviceProcAddr(dev, "vkGetImageSparseMemoryRequirements"));
QueueBindSparse = reinterpret_cast<PFN_vkQueueBindSparse>(GetDeviceProcAddr(dev, "vkQueueBindSparse"));
CreateFence = reinterpret_cast<PFN_vkCreateFence>(GetDeviceProcAddr(dev, "vkCreateFence"));
DestroyFence = reinterpret_cast<PFN_vkDestroyFence>(GetDeviceProcAddr(dev, "vkDestroyFence"));
@ -433,7 +530,8 @@ void init_dispatch_table_bottom(VkInstance instance, VkDevice dev)
DestroyBufferView = reinterpret_cast<PFN_vkDestroyBufferView>(GetDeviceProcAddr(dev, "vkDestroyBufferView"));
CreateImage = reinterpret_cast<PFN_vkCreateImage>(GetDeviceProcAddr(dev, "vkCreateImage"));
DestroyImage = reinterpret_cast<PFN_vkDestroyImage>(GetDeviceProcAddr(dev, "vkDestroyImage"));
GetImageSubresourceLayout = reinterpret_cast<PFN_vkGetImageSubresourceLayout>(GetDeviceProcAddr(dev, "vkGetImageSubresourceLayout"));
GetImageSubresourceLayout =
reinterpret_cast<PFN_vkGetImageSubresourceLayout>(GetDeviceProcAddr(dev, "vkGetImageSubresourceLayout"));
CreateImageView = reinterpret_cast<PFN_vkCreateImageView>(GetDeviceProcAddr(dev, "vkCreateImageView"));
DestroyImageView = reinterpret_cast<PFN_vkDestroyImageView>(GetDeviceProcAddr(dev, "vkDestroyImageView"));
CreateShaderModule = reinterpret_cast<PFN_vkCreateShaderModule>(GetDeviceProcAddr(dev, "vkCreateShaderModule"));
@ -442,30 +540,39 @@ void init_dispatch_table_bottom(VkInstance instance, VkDevice dev)
DestroyPipelineCache = reinterpret_cast<PFN_vkDestroyPipelineCache>(GetDeviceProcAddr(dev, "vkDestroyPipelineCache"));
GetPipelineCacheData = reinterpret_cast<PFN_vkGetPipelineCacheData>(GetDeviceProcAddr(dev, "vkGetPipelineCacheData"));
MergePipelineCaches = reinterpret_cast<PFN_vkMergePipelineCaches>(GetDeviceProcAddr(dev, "vkMergePipelineCaches"));
CreateGraphicsPipelines = reinterpret_cast<PFN_vkCreateGraphicsPipelines>(GetDeviceProcAddr(dev, "vkCreateGraphicsPipelines"));
CreateComputePipelines = reinterpret_cast<PFN_vkCreateComputePipelines>(GetDeviceProcAddr(dev, "vkCreateComputePipelines"));
CreateGraphicsPipelines =
reinterpret_cast<PFN_vkCreateGraphicsPipelines>(GetDeviceProcAddr(dev, "vkCreateGraphicsPipelines"));
CreateComputePipelines =
reinterpret_cast<PFN_vkCreateComputePipelines>(GetDeviceProcAddr(dev, "vkCreateComputePipelines"));
DestroyPipeline = reinterpret_cast<PFN_vkDestroyPipeline>(GetDeviceProcAddr(dev, "vkDestroyPipeline"));
CreatePipelineLayout = reinterpret_cast<PFN_vkCreatePipelineLayout>(GetDeviceProcAddr(dev, "vkCreatePipelineLayout"));
DestroyPipelineLayout = reinterpret_cast<PFN_vkDestroyPipelineLayout>(GetDeviceProcAddr(dev, "vkDestroyPipelineLayout"));
DestroyPipelineLayout =
reinterpret_cast<PFN_vkDestroyPipelineLayout>(GetDeviceProcAddr(dev, "vkDestroyPipelineLayout"));
CreateSampler = reinterpret_cast<PFN_vkCreateSampler>(GetDeviceProcAddr(dev, "vkCreateSampler"));
DestroySampler = reinterpret_cast<PFN_vkDestroySampler>(GetDeviceProcAddr(dev, "vkDestroySampler"));
CreateDescriptorSetLayout = reinterpret_cast<PFN_vkCreateDescriptorSetLayout>(GetDeviceProcAddr(dev, "vkCreateDescriptorSetLayout"));
DestroyDescriptorSetLayout = reinterpret_cast<PFN_vkDestroyDescriptorSetLayout>(GetDeviceProcAddr(dev, "vkDestroyDescriptorSetLayout"));
CreateDescriptorSetLayout =
reinterpret_cast<PFN_vkCreateDescriptorSetLayout>(GetDeviceProcAddr(dev, "vkCreateDescriptorSetLayout"));
DestroyDescriptorSetLayout =
reinterpret_cast<PFN_vkDestroyDescriptorSetLayout>(GetDeviceProcAddr(dev, "vkDestroyDescriptorSetLayout"));
CreateDescriptorPool = reinterpret_cast<PFN_vkCreateDescriptorPool>(GetDeviceProcAddr(dev, "vkCreateDescriptorPool"));
DestroyDescriptorPool = reinterpret_cast<PFN_vkDestroyDescriptorPool>(GetDeviceProcAddr(dev, "vkDestroyDescriptorPool"));
DestroyDescriptorPool =
reinterpret_cast<PFN_vkDestroyDescriptorPool>(GetDeviceProcAddr(dev, "vkDestroyDescriptorPool"));
ResetDescriptorPool = reinterpret_cast<PFN_vkResetDescriptorPool>(GetDeviceProcAddr(dev, "vkResetDescriptorPool"));
AllocateDescriptorSets = reinterpret_cast<PFN_vkAllocateDescriptorSets>(GetDeviceProcAddr(dev, "vkAllocateDescriptorSets"));
AllocateDescriptorSets =
reinterpret_cast<PFN_vkAllocateDescriptorSets>(GetDeviceProcAddr(dev, "vkAllocateDescriptorSets"));
FreeDescriptorSets = reinterpret_cast<PFN_vkFreeDescriptorSets>(GetDeviceProcAddr(dev, "vkFreeDescriptorSets"));
UpdateDescriptorSets = reinterpret_cast<PFN_vkUpdateDescriptorSets>(GetDeviceProcAddr(dev, "vkUpdateDescriptorSets"));
CreateFramebuffer = reinterpret_cast<PFN_vkCreateFramebuffer>(GetDeviceProcAddr(dev, "vkCreateFramebuffer"));
DestroyFramebuffer = reinterpret_cast<PFN_vkDestroyFramebuffer>(GetDeviceProcAddr(dev, "vkDestroyFramebuffer"));
CreateRenderPass = reinterpret_cast<PFN_vkCreateRenderPass>(GetDeviceProcAddr(dev, "vkCreateRenderPass"));
DestroyRenderPass = reinterpret_cast<PFN_vkDestroyRenderPass>(GetDeviceProcAddr(dev, "vkDestroyRenderPass"));
GetRenderAreaGranularity = reinterpret_cast<PFN_vkGetRenderAreaGranularity>(GetDeviceProcAddr(dev, "vkGetRenderAreaGranularity"));
GetRenderAreaGranularity =
reinterpret_cast<PFN_vkGetRenderAreaGranularity>(GetDeviceProcAddr(dev, "vkGetRenderAreaGranularity"));
CreateCommandPool = reinterpret_cast<PFN_vkCreateCommandPool>(GetDeviceProcAddr(dev, "vkCreateCommandPool"));
DestroyCommandPool = reinterpret_cast<PFN_vkDestroyCommandPool>(GetDeviceProcAddr(dev, "vkDestroyCommandPool"));
ResetCommandPool = reinterpret_cast<PFN_vkResetCommandPool>(GetDeviceProcAddr(dev, "vkResetCommandPool"));
AllocateCommandBuffers = reinterpret_cast<PFN_vkAllocateCommandBuffers>(GetDeviceProcAddr(dev, "vkAllocateCommandBuffers"));
AllocateCommandBuffers =
reinterpret_cast<PFN_vkAllocateCommandBuffers>(GetDeviceProcAddr(dev, "vkAllocateCommandBuffers"));
FreeCommandBuffers = reinterpret_cast<PFN_vkFreeCommandBuffers>(GetDeviceProcAddr(dev, "vkFreeCommandBuffers"));
BeginCommandBuffer = reinterpret_cast<PFN_vkBeginCommandBuffer>(GetDeviceProcAddr(dev, "vkBeginCommandBuffer"));
EndCommandBuffer = reinterpret_cast<PFN_vkEndCommandBuffer>(GetDeviceProcAddr(dev, "vkEndCommandBuffer"));
@ -477,16 +584,21 @@ void init_dispatch_table_bottom(VkInstance instance, VkDevice dev)
CmdSetDepthBias = reinterpret_cast<PFN_vkCmdSetDepthBias>(GetDeviceProcAddr(dev, "vkCmdSetDepthBias"));
CmdSetBlendConstants = reinterpret_cast<PFN_vkCmdSetBlendConstants>(GetDeviceProcAddr(dev, "vkCmdSetBlendConstants"));
CmdSetDepthBounds = reinterpret_cast<PFN_vkCmdSetDepthBounds>(GetDeviceProcAddr(dev, "vkCmdSetDepthBounds"));
CmdSetStencilCompareMask = reinterpret_cast<PFN_vkCmdSetStencilCompareMask>(GetDeviceProcAddr(dev, "vkCmdSetStencilCompareMask"));
CmdSetStencilWriteMask = reinterpret_cast<PFN_vkCmdSetStencilWriteMask>(GetDeviceProcAddr(dev, "vkCmdSetStencilWriteMask"));
CmdSetStencilReference = reinterpret_cast<PFN_vkCmdSetStencilReference>(GetDeviceProcAddr(dev, "vkCmdSetStencilReference"));
CmdBindDescriptorSets = reinterpret_cast<PFN_vkCmdBindDescriptorSets>(GetDeviceProcAddr(dev, "vkCmdBindDescriptorSets"));
CmdSetStencilCompareMask =
reinterpret_cast<PFN_vkCmdSetStencilCompareMask>(GetDeviceProcAddr(dev, "vkCmdSetStencilCompareMask"));
CmdSetStencilWriteMask =
reinterpret_cast<PFN_vkCmdSetStencilWriteMask>(GetDeviceProcAddr(dev, "vkCmdSetStencilWriteMask"));
CmdSetStencilReference =
reinterpret_cast<PFN_vkCmdSetStencilReference>(GetDeviceProcAddr(dev, "vkCmdSetStencilReference"));
CmdBindDescriptorSets =
reinterpret_cast<PFN_vkCmdBindDescriptorSets>(GetDeviceProcAddr(dev, "vkCmdBindDescriptorSets"));
CmdBindIndexBuffer = reinterpret_cast<PFN_vkCmdBindIndexBuffer>(GetDeviceProcAddr(dev, "vkCmdBindIndexBuffer"));
CmdBindVertexBuffers = reinterpret_cast<PFN_vkCmdBindVertexBuffers>(GetDeviceProcAddr(dev, "vkCmdBindVertexBuffers"));
CmdDraw = reinterpret_cast<PFN_vkCmdDraw>(GetDeviceProcAddr(dev, "vkCmdDraw"));
CmdDrawIndexed = reinterpret_cast<PFN_vkCmdDrawIndexed>(GetDeviceProcAddr(dev, "vkCmdDrawIndexed"));
CmdDrawIndirect = reinterpret_cast<PFN_vkCmdDrawIndirect>(GetDeviceProcAddr(dev, "vkCmdDrawIndirect"));
CmdDrawIndexedIndirect = reinterpret_cast<PFN_vkCmdDrawIndexedIndirect>(GetDeviceProcAddr(dev, "vkCmdDrawIndexedIndirect"));
CmdDrawIndexedIndirect =
reinterpret_cast<PFN_vkCmdDrawIndexedIndirect>(GetDeviceProcAddr(dev, "vkCmdDrawIndexedIndirect"));
CmdDispatch = reinterpret_cast<PFN_vkCmdDispatch>(GetDeviceProcAddr(dev, "vkCmdDispatch"));
CmdDispatchIndirect = reinterpret_cast<PFN_vkCmdDispatchIndirect>(GetDeviceProcAddr(dev, "vkCmdDispatchIndirect"));
CmdCopyBuffer = reinterpret_cast<PFN_vkCmdCopyBuffer>(GetDeviceProcAddr(dev, "vkCmdCopyBuffer"));
@ -497,7 +609,8 @@ void init_dispatch_table_bottom(VkInstance instance, VkDevice dev)
CmdUpdateBuffer = reinterpret_cast<PFN_vkCmdUpdateBuffer>(GetDeviceProcAddr(dev, "vkCmdUpdateBuffer"));
CmdFillBuffer = reinterpret_cast<PFN_vkCmdFillBuffer>(GetDeviceProcAddr(dev, "vkCmdFillBuffer"));
CmdClearColorImage = reinterpret_cast<PFN_vkCmdClearColorImage>(GetDeviceProcAddr(dev, "vkCmdClearColorImage"));
CmdClearDepthStencilImage = reinterpret_cast<PFN_vkCmdClearDepthStencilImage>(GetDeviceProcAddr(dev, "vkCmdClearDepthStencilImage"));
CmdClearDepthStencilImage =
reinterpret_cast<PFN_vkCmdClearDepthStencilImage>(GetDeviceProcAddr(dev, "vkCmdClearDepthStencilImage"));
CmdClearAttachments = reinterpret_cast<PFN_vkCmdClearAttachments>(GetDeviceProcAddr(dev, "vkCmdClearAttachments"));
CmdResolveImage = reinterpret_cast<PFN_vkCmdResolveImage>(GetDeviceProcAddr(dev, "vkCmdResolveImage"));
CmdSetEvent = reinterpret_cast<PFN_vkCmdSetEvent>(GetDeviceProcAddr(dev, "vkCmdSetEvent"));
@ -508,7 +621,8 @@ void init_dispatch_table_bottom(VkInstance instance, VkDevice dev)
CmdEndQuery = reinterpret_cast<PFN_vkCmdEndQuery>(GetDeviceProcAddr(dev, "vkCmdEndQuery"));
CmdResetQueryPool = reinterpret_cast<PFN_vkCmdResetQueryPool>(GetDeviceProcAddr(dev, "vkCmdResetQueryPool"));
CmdWriteTimestamp = reinterpret_cast<PFN_vkCmdWriteTimestamp>(GetDeviceProcAddr(dev, "vkCmdWriteTimestamp"));
CmdCopyQueryPoolResults = reinterpret_cast<PFN_vkCmdCopyQueryPoolResults>(GetDeviceProcAddr(dev, "vkCmdCopyQueryPoolResults"));
CmdCopyQueryPoolResults =
reinterpret_cast<PFN_vkCmdCopyQueryPoolResults>(GetDeviceProcAddr(dev, "vkCmdCopyQueryPoolResults"));
CmdPushConstants = reinterpret_cast<PFN_vkCmdPushConstants>(GetDeviceProcAddr(dev, "vkCmdPushConstants"));
CmdBeginRenderPass = reinterpret_cast<PFN_vkCmdBeginRenderPass>(GetDeviceProcAddr(dev, "vkCmdBeginRenderPass"));
CmdNextSubpass = reinterpret_cast<PFN_vkCmdNextSubpass>(GetDeviceProcAddr(dev, "vkCmdNextSubpass"));
@ -516,10 +630,12 @@ void init_dispatch_table_bottom(VkInstance instance, VkDevice dev)
CmdExecuteCommands = reinterpret_cast<PFN_vkCmdExecuteCommands>(GetDeviceProcAddr(dev, "vkCmdExecuteCommands"));
CreateSwapchainKHR = reinterpret_cast<PFN_vkCreateSwapchainKHR>(GetDeviceProcAddr(dev, "vkCreateSwapchainKHR"));
DestroySwapchainKHR = reinterpret_cast<PFN_vkDestroySwapchainKHR>(GetDeviceProcAddr(dev, "vkDestroySwapchainKHR"));
GetSwapchainImagesKHR = reinterpret_cast<PFN_vkGetSwapchainImagesKHR>(GetDeviceProcAddr(dev, "vkGetSwapchainImagesKHR"));
GetSwapchainImagesKHR =
reinterpret_cast<PFN_vkGetSwapchainImagesKHR>(GetDeviceProcAddr(dev, "vkGetSwapchainImagesKHR"));
AcquireNextImageKHR = reinterpret_cast<PFN_vkAcquireNextImageKHR>(GetDeviceProcAddr(dev, "vkAcquireNextImageKHR"));
QueuePresentKHR = reinterpret_cast<PFN_vkQueuePresentKHR>(GetDeviceProcAddr(dev, "vkQueuePresentKHR"));
CreateSharedSwapchainsKHR = reinterpret_cast<PFN_vkCreateSharedSwapchainsKHR>(GetDeviceProcAddr(dev, "vkCreateSharedSwapchainsKHR"));
CreateSharedSwapchainsKHR =
reinterpret_cast<PFN_vkCreateSharedSwapchainsKHR>(GetDeviceProcAddr(dev, "vkCreateSharedSwapchainsKHR"));
}
} // namespace vk

File diff suppressed because it is too large Load Diff

View File

@ -55,50 +55,23 @@ extern "C" {
_GLAPI_EXPORT __thread void* _glapi_tls_Context;
_GLAPI_EXPORT __thread struct _glapi_table* _glapi_tls_Dispatch;
int
_glapi_add_dispatch( const char * const * function_names,
const char * parameter_signature )
{
return 0;
}
int _glapi_add_dispatch(const char* const* function_names, const char* parameter_signature) { return 0; }
void
_glapi_destroy_multithread(void)
{
}
void _glapi_destroy_multithread(void) {}
void
_glapi_check_multithread(void)
{
}
void _glapi_check_multithread(void) {}
void
_glapi_set_context(void *context)
{
_glapi_tls_Context = context;
}
void _glapi_set_context(void* context) { _glapi_tls_Context = context; }
void *
_glapi_get_context()
{
return _glapi_tls_Context;
}
void* _glapi_get_context() { return _glapi_tls_Context; }
void
_glapi_set_dispatch(struct _glapi_table *dispatch)
{
_glapi_tls_Dispatch = dispatch;
}
void _glapi_set_dispatch(struct _glapi_table* dispatch) { _glapi_tls_Dispatch = dispatch; }
struct _glapi_table *
_glapi_get_dispatch()
{
struct _glapi_table* _glapi_get_dispatch() {
return _glapi_tls_Dispatch;
}
GLuint
_glapi_get_dispatch_table_size(void)
{
GLuint _glapi_get_dispatch_table_size(void) {
/*
* The dispatch table size (number of entries) is the size of the
* _glapi_table struct plus the number of dynamic entries we can add.
@ -110,20 +83,11 @@ _glapi_get_dispatch_table_size(void)
class dead_variable_visitor : public ir_hierarchical_visitor {
public:
dead_variable_visitor()
{
variables = _mesa_set_create(NULL,
_mesa_hash_pointer,
_mesa_key_pointer_equal);
}
dead_variable_visitor() { variables = _mesa_set_create(NULL, _mesa_hash_pointer, _mesa_key_pointer_equal); }
virtual ~dead_variable_visitor()
{
_mesa_set_destroy(variables, NULL);
}
virtual ~dead_variable_visitor() { _mesa_set_destroy(variables, NULL); }
virtual ir_visitor_status visit(ir_variable *ir)
{
virtual ir_visitor_status visit(ir_variable* ir) {
/* If the variable is auto or temp, add it to the set of variables that
* are candidates for removal.
*/
@ -135,8 +99,7 @@ public:
return visit_continue;
}
virtual ir_visitor_status visit(ir_dereference_variable *ir)
{
virtual ir_visitor_status visit(ir_dereference_variable* ir) {
struct set_entry* entry = _mesa_set_search(variables, ir->var);
/* If a variable is dereferenced at all, remove it from the set of
@ -148,8 +111,7 @@ public:
return visit_continue;
}
void remove_dead_variables()
{
void remove_dead_variables() {
struct set_entry* entry;
set_foreach(variables, entry) {
@ -164,13 +126,10 @@ private:
set* variables;
};
void nx_compiler::compile_shader(struct gl_context *ctx, struct gl_shader *shader)
{
struct _mesa_glsl_parse_state *state =
new(shader) _mesa_glsl_parse_state(ctx, shader->Stage, shader);
void nx_compiler::compile_shader(struct gl_context* ctx, struct gl_shader* shader) {
struct _mesa_glsl_parse_state* state = new (shader) _mesa_glsl_parse_state(ctx, shader->Stage, shader);
_mesa_glsl_compile_shader(ctx, shader, m_options.dump_ast,
m_options.dump_hir, true);
_mesa_glsl_compile_shader(ctx, shader, m_options.dump_ast, m_options.dump_hir, true);
/* Print out the resulting IR */
if (!state->error && m_options.dump_lir) {
@ -178,16 +137,13 @@ void nx_compiler::compile_shader(struct gl_context *ctx, struct gl_shader *shade
}
}
nx_compiler::nx_compiler()
{
nx_compiler::nx_compiler() {
m_options.glsl_version = 330;
m_options.do_link = true;
}
nx_compiler::~nx_compiler()
{
if (m_ownsCtx)
{
nx_compiler::~nx_compiler() {
if (m_ownsCtx) {
_mesa_glsl_release_types();
_mesa_glsl_release_builtin_functions();
if (m_st)
@ -197,9 +153,7 @@ nx_compiler::~nx_compiler()
}
}
bool nx_compiler::initialize(struct pipe_screen *screen, struct st_context *st,
const struct standalone_options *o)
{
bool nx_compiler::initialize(struct pipe_screen* screen, struct st_context* st, const struct standalone_options* o) {
m_screen = screen;
m_st = st;
if (o)
@ -207,8 +161,7 @@ bool nx_compiler::initialize(struct pipe_screen *screen, struct st_context *st,
return true;
}
bool nx_compiler::initialize(const struct standalone_options* o)
{
bool nx_compiler::initialize(const struct standalone_options* o) {
m_ownsCtx = true;
bool glsl_es;
@ -289,16 +242,14 @@ bool nx_compiler::initialize(const struct standalone_options* o)
return false;
screen->refcount = 1;
struct pipe_context* p_ctx = screen->base.context_create(&screen->base, nullptr, 0);
if (!p_ctx)
{
if (!p_ctx) {
screen->base.destroy(&screen->base);
return false;
}
st_config_options opts = {};
struct st_context* st = st_create_context(use_api, p_ctx, nullptr, nullptr, &opts, false);
if (!st)
{
if (!st) {
screen->base.destroy(&screen->base);
return false;
}
@ -306,17 +257,14 @@ bool nx_compiler::initialize(const struct standalone_options* o)
return initialize(&screen->base, st);
}
nx_shader_stage_object::nx_shader_stage_object(const nx_shader_stage_object& other)
: m_parent(other.m_parent)
{
nx_shader_stage_object::nx_shader_stage_object(const nx_shader_stage_object& other) : m_parent(other.m_parent) {
if (!other.m_shader || !m_parent)
return;
struct gl_context* ctx = m_parent->m_st->ctx;
_mesa_reference_shader(ctx, &m_shader, other.m_shader);
}
nx_shader_stage_object& nx_shader_stage_object::operator=(const nx_shader_stage_object& other)
{
nx_shader_stage_object& nx_shader_stage_object::operator=(const nx_shader_stage_object& other) {
m_parent = other.m_parent;
if (!other.m_shader || !m_parent)
return *this;
@ -325,44 +273,35 @@ nx_shader_stage_object& nx_shader_stage_object::operator=(const nx_shader_stage_
return *this;
}
void nx_shader_stage_object::reset()
{
void nx_shader_stage_object::reset() {
if (!m_shader || !m_parent)
return;
struct gl_context* ctx = m_parent->m_st->ctx;
_mesa_reference_shader(ctx, &m_shader, nullptr);
}
nx_shader_stage_object::operator bool() const
{
nx_shader_stage_object::operator bool() const {
if (!m_shader)
return false;
return m_shader->CompileStatus;
}
nx_shader_stage nx_shader_stage_object::stage() const
{
return nx_shader_stage(m_shader->Stage);
}
nx_shader_stage nx_shader_stage_object::stage() const { return nx_shader_stage(m_shader->Stage); }
const char* nx_shader_stage_object::info_log() const
{
const char* nx_shader_stage_object::info_log() const {
if (!m_shader)
return nullptr;
return m_shader->InfoLog;
}
nx_linked_shader::nx_linked_shader(const nx_linked_shader& other)
: m_parent(other.m_parent)
{
nx_linked_shader::nx_linked_shader(const nx_linked_shader& other) : m_parent(other.m_parent) {
if (!other.m_program || !m_parent)
return;
struct gl_context* ctx = m_parent->m_st->ctx;
_mesa_reference_shader_program(ctx, &m_program, other.m_program);
}
nx_linked_shader& nx_linked_shader::operator=(const nx_linked_shader& other)
{
nx_linked_shader& nx_linked_shader::operator=(const nx_linked_shader& other) {
m_parent = other.m_parent;
if (!other.m_program || !m_parent)
return *this;
@ -371,16 +310,14 @@ nx_linked_shader& nx_linked_shader::operator=(const nx_linked_shader& other)
return *this;
}
void nx_linked_shader::reset()
{
void nx_linked_shader::reset() {
if (!m_program || !m_parent)
return;
struct gl_context* ctx = m_parent->m_st->ctx;
_mesa_reference_shader_program(ctx, &m_program, nullptr);
}
nx_shader_stage_object nx_compiler::compile(nx_shader_stage type, const char *source)
{
nx_shader_stage_object nx_compiler::compile(nx_shader_stage type, const char* source) {
struct gl_context* ctx = m_st->ctx;
nx_shader_stage_object ret(*this);
@ -399,8 +336,7 @@ nx_shader_stage_object nx_compiler::compile(nx_shader_stage type, const char *so
return ret;
}
nx_linked_shader nx_compiler::link(unsigned num_stages, const nx_shader_stage_object **stages, std::string* infoLog)
{
nx_linked_shader nx_compiler::link(unsigned num_stages, const nx_shader_stage_object** stages, std::string* infoLog) {
nx_linked_shader ret(*this);
int status = EXIT_SUCCESS;
struct gl_context* ctx = m_st->ctx;
@ -444,12 +380,7 @@ nx_linked_shader nx_compiler::link(unsigned num_stages, const nx_shader_stage_ob
whole_program->data->LinkStatus = LINKING_SUCCESS;
whole_program->_LinkedShaders[stage] =
link_intrastage_shaders(whole_program /* mem_ctx */,
ctx,
whole_program,
whole_program->Shaders,
1,
true);
link_intrastage_shaders(whole_program /* mem_ctx */, ctx, whole_program, whole_program->Shaders, 1, true);
whole_program->_LinkedShaders[stage]->Program->Target = _mesa_shader_stage_to_program(stage);
/* Par-linking can fail, for example, if there are undefined external
@ -458,22 +389,15 @@ nx_linked_shader nx_compiler::link(unsigned num_stages, const nx_shader_stage_ob
if (whole_program->_LinkedShaders[stage] != NULL) {
assert(whole_program->data->LinkStatus);
struct gl_shader_compiler_options *const compiler_options =
&ctx->Const.ShaderCompilerOptions[stage];
struct gl_shader_compiler_options* const compiler_options = &ctx->Const.ShaderCompilerOptions[stage];
exec_list *const ir =
whole_program->_LinkedShaders[stage]->ir;
exec_list* const ir = whole_program->_LinkedShaders[stage]->ir;
bool progress;
do {
progress = do_function_inlining(ir);
progress = do_common_optimization(ir,
false,
false,
compiler_options,
true)
&& progress;
progress = do_common_optimization(ir, false, false, compiler_options, true) && progress;
} while (progress);
}
}
@ -519,23 +443,18 @@ nx_linked_shader nx_compiler::link(unsigned num_stages, const nx_shader_stage_ob
return nx_linked_shader(*this);
}
static void
SizeProgramBuffer(const nvc0_program *prog, size_t &sz)
{
static void SizeProgramBuffer(const nvc0_program* prog, size_t& sz) {
sz += 140;
sz += prog->code_size;
}
template<class T> static void
OutputField(T f, uint8_t *&ptr)
{
template <class T>
static void OutputField(T f, uint8_t*& ptr) {
memcpy(ptr, &f, sizeof(f));
ptr += sizeof(f);
}
static void
BuildProgramBuffer(const nvc0_program *prog, uint8_t *&ptr)
{
static void BuildProgramBuffer(const nvc0_program* prog, uint8_t*& ptr) {
OutputField(prog->type, ptr);
OutputField(prog->translated, ptr);
OutputField(prog->need_tls, ptr);
@ -572,9 +491,9 @@ BuildProgramBuffer(const nvc0_program *prog, uint8_t *&ptr)
ptr += prog->code_size;
}
std::pair<std::shared_ptr<uint8_t[]>, size_t>
nx_compiler::offline_link(unsigned num_stages, const nx_shader_stage_object **stages, std::string *infoLog)
{
std::pair<std::shared_ptr<uint8_t[]>, size_t> nx_compiler::offline_link(unsigned num_stages,
const nx_shader_stage_object** stages,
std::string* infoLog) {
std::pair<std::shared_ptr<uint8_t[]>, size_t> ret = {};
auto whole_program = link(num_stages, stages, infoLog);
if (!whole_program)

View File

@ -1,13 +1,10 @@
#include "boo/graphicsdev/nx_compiler.hpp"
int main(int argc, char** argv)
{
int main(int argc, char** argv) {
nx_compiler c;
c.initialize();
nx_shader_stage_object objs[] =
{
c.compile(nx_shader_stage::VERTEX,
nx_shader_stage_object objs[] = {c.compile(nx_shader_stage::VERTEX,
"#version 330\n"
"#extension GL_ARB_separate_shader_objects: enable\n"
"#extension GL_ARB_shading_language_420pack: enable\n"
@ -30,8 +27,7 @@ int main(int argc, char** argv)
"void main()\n"
"{\n"
" out_frag = texture(texs[0], out_uv) + texture(texs[1], out_uv);\n"
"}")
};
"}")};
std::string log;
auto linkData = c.link(2, objs, &log);

View File

@ -3,76 +3,62 @@
#include "IHIDDevice.hpp"
#include <cstdarg>
namespace boo
{
namespace boo {
DeviceBase::DeviceBase(uint64_t typeHash, DeviceToken* token)
: m_typeHash(typeHash), m_token(token)
{
}
DeviceBase::DeviceBase(uint64_t typeHash, DeviceToken* token) : m_typeHash(typeHash), m_token(token) {}
void DeviceBase::_deviceDisconnected()
{
void DeviceBase::_deviceDisconnected() {
deviceDisconnected();
m_token = nullptr;
if (m_hidDev)
{
if (m_hidDev) {
m_hidDev->_deviceDisconnected();
m_hidDev.reset();
}
}
void DeviceBase::closeDevice()
{
void DeviceBase::closeDevice() {
if (m_token)
m_token->_deviceClose();
}
void DeviceBase::deviceError(const char* error, ...)
{
void DeviceBase::deviceError(const char* error, ...) {
va_list vl;
va_start(vl, error);
vfprintf(stderr, error, vl);
va_end(vl);
}
bool DeviceBase::sendUSBInterruptTransfer(const uint8_t* data, size_t length)
{
bool DeviceBase::sendUSBInterruptTransfer(const uint8_t* data, size_t length) {
if (m_hidDev)
return m_hidDev->_sendUSBInterruptTransfer(data, length);
return false;
}
size_t DeviceBase::receiveUSBInterruptTransfer(uint8_t* data, size_t length)
{
size_t DeviceBase::receiveUSBInterruptTransfer(uint8_t* data, size_t length) {
if (m_hidDev)
return m_hidDev->_receiveUSBInterruptTransfer(data, length);
return false;
}
unsigned DeviceBase::getVendorId()
{
unsigned DeviceBase::getVendorId() {
if (m_token)
return m_token->getVendorId();
return -1;
}
unsigned DeviceBase::getProductId()
{
unsigned DeviceBase::getProductId() {
if (m_token)
return m_token->getProductId();
return -1;
}
std::string_view DeviceBase::getVendorName()
{
std::string_view DeviceBase::getVendorName() {
if (m_token)
return m_token->getVendorName();
return {};
}
std::string_view DeviceBase::getProductName()
{
std::string_view DeviceBase::getProductName() {
if (m_token)
return m_token->getProductName();
return {};
@ -80,34 +66,30 @@ std::string_view DeviceBase::getProductName()
#if _WIN32
#if !WINDOWS_STORE
const PHIDP_PREPARSED_DATA DeviceBase::getReportDescriptor()
{
const PHIDP_PREPARSED_DATA DeviceBase::getReportDescriptor() {
if (m_hidDev)
return m_hidDev->_getReportDescriptor();
return {};
}
#endif
#else
std::vector<uint8_t> DeviceBase::getReportDescriptor()
{
std::vector<uint8_t> DeviceBase::getReportDescriptor() {
if (m_hidDev)
return m_hidDev->_getReportDescriptor();
return {};
}
#endif
bool DeviceBase::sendHIDReport(const uint8_t* data, size_t length, HIDReportType tp, uint32_t message)
{
bool DeviceBase::sendHIDReport(const uint8_t* data, size_t length, HIDReportType tp, uint32_t message) {
if (m_hidDev)
return m_hidDev->_sendHIDReport(data, length, tp, message);
return false;
}
size_t DeviceBase::receiveHIDReport(uint8_t* data, size_t length, HIDReportType tp, uint32_t message)
{
size_t DeviceBase::receiveHIDReport(uint8_t* data, size_t length, HIDReportType tp, uint32_t message) {
if (m_hidDev)
return m_hidDev->_receiveHIDReport(data, length, tp, message);
return 0;
}
}
} // namespace boo

View File

@ -6,33 +6,28 @@
#include <usbiodef.h>
#endif
namespace boo
{
namespace boo {
DeviceFinder* DeviceFinder::skDevFinder = nullptr;
#if _WIN32 && !WINDOWS_STORE
/* Windows-specific WM_DEVICECHANGED handler */
LRESULT DeviceFinder::winDevChangedHandler(WPARAM wParam, LPARAM lParam)
{
LRESULT DeviceFinder::winDevChangedHandler(WPARAM wParam, LPARAM lParam) {
PDEV_BROADCAST_HDR dbh = (PDEV_BROADCAST_HDR)lParam;
PDEV_BROADCAST_DEVICEINTERFACE dbhi = (PDEV_BROADCAST_DEVICEINTERFACE)lParam;
DeviceFinder* finder = instance();
if (!finder)
return 0;
if (wParam == DBT_DEVICEARRIVAL)
{
if (dbh->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE)
{
if (wParam == DBT_DEVICEARRIVAL) {
if (dbh->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) {
DeviceType type = DeviceType::None;
if (dbhi->dbcc_classguid == GUID_DEVINTERFACE_USB_DEVICE)
type = DeviceType::USB;
else if (dbhi->dbcc_classguid == GUID_DEVINTERFACE_HID)
type = DeviceType::HID;
if (type != DeviceType::None)
{
if (type != DeviceType::None) {
#ifdef UNICODE
char devPath[1024];
wcstombs(devPath, dbhi->dbcc_name, 1024);
@ -42,19 +37,15 @@ LRESULT DeviceFinder::winDevChangedHandler(WPARAM wParam, LPARAM lParam)
#endif
}
}
}
else if (wParam == DBT_DEVICEREMOVECOMPLETE)
{
if (dbh->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE)
{
} else if (wParam == DBT_DEVICEREMOVECOMPLETE) {
if (dbh->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) {
DeviceType type = DeviceType::None;
if (dbhi->dbcc_classguid == GUID_DEVINTERFACE_USB_DEVICE)
type = DeviceType::USB;
else if (dbhi->dbcc_classguid == GUID_DEVINTERFACE_HID)
type = DeviceType::HID;
if (type != DeviceType::None)
{
if (type != DeviceType::None) {
#ifdef UNICODE
char devPath[1024];
wcstombs(devPath, dbhi->dbcc_name, 1024);
@ -70,4 +61,4 @@ LRESULT DeviceFinder::winDevChangedHandler(WPARAM wParam, LPARAM lParam)
}
#endif
}
} // namespace boo

View File

@ -3,30 +3,23 @@
#include "boo/inputdev/GenericPad.hpp"
#include "IHIDDevice.hpp"
namespace boo
{
namespace boo {
extern const DeviceSignature BOO_DEVICE_SIGS[];
bool DeviceSignature::DeviceMatchToken(const DeviceToken& token, const TDeviceSignatureSet& sigSet)
{
if (token.getDeviceType() == DeviceType::HID)
{
bool DeviceSignature::DeviceMatchToken(const DeviceToken& token, const TDeviceSignatureSet& sigSet) {
if (token.getDeviceType() == DeviceType::HID) {
uint64_t genPadHash = dev_typeid(GenericPad);
bool hasGenericPad = false;
for (const DeviceSignature* sig : sigSet)
{
if (sig->m_vid == token.getVendorId() && sig->m_pid == token.getProductId() &&
sig->m_type != DeviceType::HID)
for (const DeviceSignature* sig : sigSet) {
if (sig->m_vid == token.getVendorId() && sig->m_pid == token.getProductId() && sig->m_type != DeviceType::HID)
return false;
if (sig->m_typeHash == genPadHash)
hasGenericPad = true;
}
return hasGenericPad;
}
for (const DeviceSignature* sig : sigSet)
{
for (const DeviceSignature* sig : sigSet) {
if (sig->m_vid == token.getVendorId() && sig->m_pid == token.getProductId())
return true;
}
@ -34,8 +27,7 @@ bool DeviceSignature::DeviceMatchToken(const DeviceToken& token, const TDeviceSi
}
std::shared_ptr<IHIDDevice> IHIDDeviceNew(DeviceToken& token, const std::shared_ptr<DeviceBase>& devImp);
std::shared_ptr<DeviceBase> DeviceSignature::DeviceNew(DeviceToken& token)
{
std::shared_ptr<DeviceBase> DeviceSignature::DeviceNew(DeviceToken& token) {
std::shared_ptr<DeviceBase> retval;
/* Perform signature-matching to find the appropriate device-factory */
@ -43,20 +35,16 @@ std::shared_ptr<DeviceBase> DeviceSignature::DeviceNew(DeviceToken& token)
const DeviceSignature* sigIter = BOO_DEVICE_SIGS;
unsigned targetVid = token.getVendorId();
unsigned targetPid = token.getProductId();
while (sigIter->m_name)
{
if (sigIter->m_vid == targetVid && sigIter->m_pid == targetPid)
{
while (sigIter->m_name) {
if (sigIter->m_vid == targetVid && sigIter->m_pid == targetPid) {
foundSig = sigIter;
break;
}
++sigIter;
}
if (!foundSig)
{
if (!foundSig) {
/* Try Generic HID devices */
if (token.getDeviceType() == DeviceType::HID)
{
if (token.getDeviceType() == DeviceType::HID) {
retval = std::make_shared<GenericPad>(&token);
if (!retval)
return nullptr;
@ -86,4 +74,4 @@ std::shared_ptr<DeviceBase> DeviceSignature::DeviceNew(DeviceToken& token)
return retval;
}
}
} // namespace boo

View File

@ -3,8 +3,7 @@
#include <cstdio>
#include <cstring>
namespace boo
{
namespace boo {
/*
* Reference: https://github.com/ToadKing/wii-u-gc-adapter/blob/master/wii-u-gc-adapter.c
*/
@ -14,12 +13,10 @@ DolphinSmashAdapter::DolphinSmashAdapter(DeviceToken* token)
DolphinSmashAdapter::~DolphinSmashAdapter() {}
static inline EDolphinControllerType parseType(unsigned char status)
{
static inline EDolphinControllerType parseType(unsigned char status) {
EDolphinControllerType type =
EDolphinControllerType(status) & (EDolphinControllerType::Normal | EDolphinControllerType::Wavebird);
switch (type)
{
switch (type) {
case EDolphinControllerType::Normal:
case EDolphinControllerType::Wavebird:
return type;
@ -28,8 +25,7 @@ static inline EDolphinControllerType parseType(unsigned char status)
}
}
static inline EDolphinControllerType parseState(DolphinControllerState* stateOut, uint8_t* payload, bool& rumble)
{
static inline EDolphinControllerType parseState(DolphinControllerState* stateOut, uint8_t* payload, bool& rumble) {
memset(stateOut, 0, sizeof(DolphinControllerState));
unsigned char status = payload[0];
EDolphinControllerType type = parseType(status);
@ -48,14 +44,12 @@ static inline EDolphinControllerType parseState(DolphinControllerState* stateOut
return type;
}
void DolphinSmashAdapter::initialCycle()
{
void DolphinSmashAdapter::initialCycle() {
uint8_t handshakePayload[] = {0x13};
sendUSBInterruptTransfer(handshakePayload, sizeof(handshakePayload));
}
void DolphinSmashAdapter::transferCycle()
{
void DolphinSmashAdapter::transferCycle() {
uint8_t payload[37];
size_t recvSz = receiveUSBInterruptTransfer(payload, sizeof(payload));
if (recvSz != 37 || payload[0] != 0x21)
@ -70,13 +64,11 @@ void DolphinSmashAdapter::transferCycle()
/* Parse controller states */
uint8_t* controller = &payload[1];
uint8_t rumbleMask = 0;
for (uint32_t i = 0; i < 4; i++, controller += 9)
{
for (uint32_t i = 0; i < 4; i++, controller += 9) {
DolphinControllerState state;
bool rumble = false;
EDolphinControllerType type = parseState(&state, controller, rumble);
if (type != EDolphinControllerType::None && !(m_knownControllers & 1 << i))
{
if (type != EDolphinControllerType::None && !(m_knownControllers & 1 << i)) {
m_leftStickCal[0] = state.m_leftStick[0];
m_leftStickCal[1] = state.m_leftStick[1];
m_rightStickCal[0] = state.m_rightStick[0];
@ -85,14 +77,11 @@ void DolphinSmashAdapter::transferCycle()
m_triggersCal[1] = state.m_analogTriggers[1];
m_knownControllers |= 1 << i;
m_callback->controllerConnected(i, type);
}
else if (type == EDolphinControllerType::None && (m_knownControllers & 1 << i))
{
} else if (type == EDolphinControllerType::None && (m_knownControllers & 1 << i)) {
m_knownControllers &= ~(1 << i);
m_callback->controllerDisconnected(i);
}
if (m_knownControllers & 1 << i)
{
if (m_knownControllers & 1 << i) {
state.m_leftStick[0] = state.m_leftStick[0] - m_leftStickCal[0];
state.m_leftStick[1] = state.m_leftStick[1] - m_leftStickCal[1];
state.m_rightStick[0] = state.m_rightStick[0] - m_rightStickCal[0];
@ -106,11 +95,9 @@ void DolphinSmashAdapter::transferCycle()
/* Send rumble message (if needed) */
uint8_t rumbleReq = m_rumbleRequest & rumbleMask;
if (rumbleReq != m_rumbleState)
{
if (rumbleReq != m_rumbleState) {
uint8_t rumbleMessage[5] = {0x11};
for (int i = 0; i < 4; ++i)
{
for (int i = 0; i < 4; ++i) {
if (rumbleReq & 1 << i)
rumbleMessage[i + 1] = 1;
else if (m_hardStop[i])
@ -124,18 +111,14 @@ void DolphinSmashAdapter::transferCycle()
}
}
void DolphinSmashAdapter::finalCycle()
{
void DolphinSmashAdapter::finalCycle() {
uint8_t rumbleMessage[5] = {0x11, 0, 0, 0, 0};
sendUSBInterruptTransfer(rumbleMessage, sizeof(rumbleMessage));
}
void DolphinSmashAdapter::deviceDisconnected()
{
for (uint32_t i = 0; i < 4; i++)
{
if (m_knownControllers & 1 << i)
{
void DolphinSmashAdapter::deviceDisconnected() {
for (uint32_t i = 0; i < 4; i++) {
if (m_knownControllers & 1 << i) {
m_knownControllers &= ~(1 << i);
std::lock_guard<std::mutex> lk(m_callbackLock);
if (m_callback)
@ -170,30 +153,23 @@ void DolphinSmashAdapter::deviceDisconnected()
static int16_t pad_clampregion[8] = {30, 180, 15, 72, 40, 15, 59, 31};
static void pad_clampstick(int16_t& px, int16_t& py, int16_t max, int16_t xy, int16_t min)
{
static void pad_clampstick(int16_t& px, int16_t& py, int16_t max, int16_t xy, int16_t min) {
int x = px;
int y = py;
int signX;
int signY;
int d;
if (x > 0)
{
if (x > 0) {
signX = 1;
}
else
{
} else {
signX = -1;
x = -x;
}
if (y > 0)
{
if (y > 0) {
signY = 1;
}
else
{
} else {
signY = -1;
y = -y;
}
@ -203,35 +179,26 @@ static void pad_clampstick(int16_t& px, int16_t& py, int16_t max, int16_t xy, in
else
x -= min;
if (y <= min)
{
if (y <= min) {
y = 0;
}
else
{
} else {
y -= min;
}
if (x == 0 && y == 0)
{
if (x == 0 && y == 0) {
px = py = 0;
return;
}
if (xy * y <= xy * x)
{
if (xy * y <= xy * x) {
d = xy * x + (max - xy) * y;
if (xy * max < d)
{
if (xy * max < d) {
x = int16_t(xy * max * x / d);
y = int16_t(xy * max * y / d);
}
}
else
{
} else {
d = xy * y + (max - xy) * x;
if (xy * max < d)
{
if (xy * max < d) {
x = int16_t(xy * max * x / d);
y = int16_t(xy * max * y / d);
}
@ -241,27 +208,24 @@ static void pad_clampstick(int16_t& px, int16_t& py, int16_t max, int16_t xy, in
py = int16_t(signY * y);
}
static void pad_clamptrigger(int16_t& trigger)
{
static void pad_clamptrigger(int16_t& trigger) {
int16_t min, max;
min = pad_clampregion[0];
max = pad_clampregion[1];
if (min > trigger)
trigger = 0;
else
{
else {
if (max < trigger)
trigger = max;
trigger -= min;
}
}
void DolphinControllerState::clamp()
{
void DolphinControllerState::clamp() {
pad_clampstick(m_leftStick[0], m_leftStick[1], pad_clampregion[3], pad_clampregion[4], pad_clampregion[2]);
pad_clampstick(m_rightStick[0], m_rightStick[1], pad_clampregion[6], pad_clampregion[7], pad_clampregion[5]);
pad_clamptrigger(m_analogTriggers[0]);
pad_clamptrigger(m_analogTriggers[1]);
}
}
} // namespace boo

View File

@ -20,41 +20,27 @@ static inline uint16_t bswap16(uint16_t val) {return __builtin_byteswap(val);}
#define RAD_TO_DEG (180.f / M_PIF)
namespace boo
{
static const uint8_t defaultReport[49] = {
0x01,
0x01, 0xff, 0x00, 0xff, 0x00,
0xff, 0x80, 0x00, 0x00, 0x00,
0xff, 0x27, 0x10, 0x00, 0x32,
0xff, 0x27, 0x10, 0x00, 0x32,
0xff, 0x27, 0x10, 0x00, 0x32,
0xff, 0x27, 0x10, 0x00, 0x32,
0x00, 0x00, 0x00, 0x00, 0x00
};
namespace boo {
static const uint8_t defaultReport[49] = {0x01, 0x01, 0xff, 0x00, 0xff, 0x00, 0xff, 0x80, 0x00, 0x00, 0x00, 0xff,
0x27, 0x10, 0x00, 0x32, 0xff, 0x27, 0x10, 0x00, 0x32, 0xff, 0x27, 0x10,
0x00, 0x32, 0xff, 0x27, 0x10, 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00};
DualshockPad::DualshockPad(DeviceToken* token)
: TDeviceBase<IDualshockPadCallback>(dev_typeid(DualshockPad), token),
m_rumbleRequest(EDualshockMotor::None),
m_rumbleState(EDualshockMotor::None)
{
: TDeviceBase<IDualshockPadCallback>(dev_typeid(DualshockPad), token)
, m_rumbleRequest(EDualshockMotor::None)
, m_rumbleState(EDualshockMotor::None) {
memcpy(m_report.buf, defaultReport, 49);
}
DualshockPad::~DualshockPad()
{
DualshockPad::~DualshockPad() {}
}
void DualshockPad::deviceDisconnected()
{
void DualshockPad::deviceDisconnected() {
std::lock_guard<std::mutex> lk(m_callbackLock);
if (m_callback)
m_callback->controllerDisconnected();
}
void DualshockPad::initialCycle()
{
void DualshockPad::initialCycle() {
#if 0
uint8_t setupCommand[5] = {0xF4, 0x42, 0x0c, 0x00, 0x00}; //Tells controller to start sending changes on in pipe
if (!sendHIDReport(setupCommand, 5, HIDReportType::Feature, 0xF4))
@ -69,12 +55,9 @@ void DualshockPad::initialCycle()
#endif
}
void DualshockPad::transferCycle()
{
}
void DualshockPad::transferCycle() {}
void DualshockPad::finalCycle()
{
void DualshockPad::finalCycle() {
m_report.rumble.leftDuration = 0;
m_report.rumble.leftForce = 0;
m_report.rumble.rightDuration = 0;
@ -82,8 +65,7 @@ void DualshockPad::finalCycle()
sendHIDReport(m_report.buf, sizeof(m_report), HIDReportType::Output, 0x01);
}
void DualshockPad::receivedHIDReport(const uint8_t* data, size_t length, HIDReportType tp, uint32_t message)
{
void DualshockPad::receivedHIDReport(const uint8_t* data, size_t length, HIDReportType tp, uint32_t message) {
if (message != 1 || length != 49 || tp != HIDReportType::Input)
return;
DualshockPadState state = *reinterpret_cast<const DualshockPadState*>(data);
@ -106,34 +88,25 @@ void DualshockPad::receivedHIDReport(const uint8_t* data, size_t length, HIDRepo
m_callback->controllerUpdate(*this, state);
}
if (m_rumbleRequest != m_rumbleState)
{
if ((m_rumbleRequest & EDualshockMotor::Left) != EDualshockMotor::None)
{
if (m_rumbleRequest != m_rumbleState) {
if ((m_rumbleRequest & EDualshockMotor::Left) != EDualshockMotor::None) {
m_report.rumble.leftDuration = m_rumbleDuration[0];
m_report.rumble.leftForce = m_rumbleIntensity[0];
}
else
{
} else {
m_report.rumble.leftDuration = 0;
m_report.rumble.leftForce = 0;
}
if ((m_rumbleRequest & EDualshockMotor::Right) != EDualshockMotor::None)
{
if ((m_rumbleRequest & EDualshockMotor::Right) != EDualshockMotor::None) {
m_report.rumble.rightDuration = m_rumbleDuration[1];
m_report.rumble.rightOn = m_rumbleIntensity[1] > 0;
}
else
{
} else {
m_report.rumble.rightDuration = 0;
m_report.rumble.rightOn = false;
}
sendHIDReport(m_report.buf, sizeof(m_report), HIDReportType::Output, 0x01);
m_rumbleState = m_rumbleRequest;
}
else
{
} else {
if (state.m_reserved5[8] & 0x80)
m_rumbleRequest &= ~EDualshockMotor::Right;
if (state.m_reserved5[7] & 0x01)
@ -142,4 +115,4 @@ void DualshockPad::receivedHIDReport(const uint8_t* data, size_t length, HIDRepo
}
}
} // boo
} // namespace boo

View File

@ -1,26 +1,19 @@
#include "boo/inputdev/GenericPad.hpp"
#include "boo/inputdev/DeviceToken.hpp"
namespace boo
{
namespace boo {
GenericPad::GenericPad(DeviceToken* token)
: TDeviceBase<IGenericPadCallback>(dev_typeid(GenericPad), token)
{
}
GenericPad::GenericPad(DeviceToken* token) : TDeviceBase<IGenericPadCallback>(dev_typeid(GenericPad), token) {}
GenericPad::~GenericPad() {}
void GenericPad::deviceDisconnected()
{
void GenericPad::deviceDisconnected() {
std::lock_guard<std::mutex> lk(m_callbackLock);
if (m_callback)
m_callback->controllerDisconnected();
}
void GenericPad::initialCycle()
{
void GenericPad::initialCycle() {
#if _WIN32
#if !WINDOWS_STORE
const PHIDP_PREPARSED_DATA reportDesc = getReportDescriptor();
@ -35,23 +28,19 @@ void GenericPad::initialCycle()
m_callback->controllerConnected();
}
void GenericPad::receivedHIDReport(const uint8_t* data, size_t length, HIDReportType tp, uint32_t message)
{
void GenericPad::receivedHIDReport(const uint8_t* data, size_t length, HIDReportType tp, uint32_t message) {
std::lock_guard<std::mutex> lk(m_callbackLock);
if (length == 0 || tp != HIDReportType::Input || !m_callback)
return;
std::function<bool(const HIDMainItem&, int32_t)> func =
[this](const HIDMainItem& item, int32_t value)
{
std::function<bool(const HIDMainItem&, int32_t)> func = [this](const HIDMainItem& item, int32_t value) {
m_callback->valueUpdate(item, value);
return true;
};
m_parser.ScanValues(func, data, length);
}
void GenericPad::enumerateValues(const std::function<bool(const HIDMainItem& item)>& valueCB) const
{
void GenericPad::enumerateValues(const std::function<bool(const HIDMainItem& item)>& valueCB) const {
m_parser.EnumerateValues(valueCB);
}
}
} // namespace boo

View File

@ -1,22 +1,15 @@
#include "boo/inputdev/IHIDListener.hpp"
#include "boo/inputdev/DeviceFinder.hpp"
namespace boo {
namespace boo
{
class HIDListenerBSD final : public IHIDListener
{
class HIDListenerBSD final : public IHIDListener {
DeviceFinder& m_finder;
public:
HIDListenerBSD(DeviceFinder& finder)
: m_finder(finder)
{
}
~HIDListenerBSD()
{
}
public:
HIDListenerBSD(DeviceFinder& finder) : m_finder(finder) {}
~HIDListenerBSD() {}
bool startScanning() { return false; }
bool stopScanning() { return false; }
@ -24,8 +17,5 @@ public:
bool scanNow() { return false; }
};
IHIDListener* IHIDListenerNew(DeviceFinder &finder)
{
return new HIDListenerBSD(finder);
}
}
IHIDListener* IHIDListenerNew(DeviceFinder& finder) { return new HIDListenerBSD(finder); }
} // namespace boo

View File

@ -5,11 +5,9 @@
#include "IOKitPointer.hpp"
#include <thread>
namespace boo
{
namespace boo {
class HIDDeviceIOKit : public IHIDDevice
{
class HIDDeviceIOKit : public IHIDDevice {
DeviceToken& m_token;
std::shared_ptr<DeviceBase> m_devImp;
@ -25,20 +23,16 @@ class HIDDeviceIOKit : public IHIDDevice
std::condition_variable m_initCond;
std::thread m_thread;
bool _sendUSBInterruptTransfer(const uint8_t* data, size_t length)
{
if (m_usbIntf)
{
bool _sendUSBInterruptTransfer(const uint8_t* data, size_t length) {
if (m_usbIntf) {
IOReturn res = m_usbIntf->WritePipe(m_usbIntf.storage(), m_usbIntfOutPipe, (void*)data, length);
return res == kIOReturnSuccess;
}
return false;
}
size_t _receiveUSBInterruptTransfer(uint8_t* data, size_t length)
{
if (m_usbIntf)
{
size_t _receiveUSBInterruptTransfer(uint8_t* data, size_t length) {
if (m_usbIntf) {
UInt32 readSize = length;
IOReturn res = m_usbIntf->ReadPipe(m_usbIntf.storage(), m_usbIntfInPipe, data, &readSize);
if (res != kIOReturnSuccess)
@ -48,12 +42,9 @@ class HIDDeviceIOKit : public IHIDDevice
return 0;
}
std::vector<uint8_t> _getReportDescriptor()
{
if (m_hidIntf)
{
if (CFTypeRef desc = IOHIDDeviceGetProperty(m_hidIntf.get(), CFSTR(kIOHIDReportDescriptorKey)))
{
std::vector<uint8_t> _getReportDescriptor() {
if (m_hidIntf) {
if (CFTypeRef desc = IOHIDDeviceGetProperty(m_hidIntf.get(), CFSTR(kIOHIDReportDescriptorKey))) {
CFIndex len = CFDataGetLength(CFDataRef(desc));
std::vector<uint8_t> ret(len, '\0');
CFDataGetBytes(CFDataRef(desc), CFRangeMake(0, len), &ret[0]);
@ -63,22 +54,18 @@ class HIDDeviceIOKit : public IHIDDevice
return {};
}
bool _sendHIDReport(const uint8_t* data, size_t length, HIDReportType tp, uint32_t message)
{
bool _sendHIDReport(const uint8_t* data, size_t length, HIDReportType tp, uint32_t message) {
/* HACK: A bug in IOBluetoothGamepadHIDDriver prevents raw output report transmission
* USB driver appears to work correctly */
if (m_hidIntf && !m_isBt)
{
if (m_hidIntf && !m_isBt) {
IOReturn res = IOHIDDeviceSetReport(m_hidIntf.get(), IOHIDReportType(tp), message, data, length);
return res == kIOReturnSuccess;
}
return false;
}
size_t _receiveHIDReport(uint8_t* data, size_t length, HIDReportType tp, uint32_t message)
{
if (m_hidIntf)
{
size_t _receiveHIDReport(uint8_t* data, size_t length, HIDReportType tp, uint32_t message) {
if (m_hidIntf) {
CFIndex readSize = length;
IOReturn res = IOHIDDeviceGetReport(m_hidIntf.get(), IOHIDReportType(tp), message, data, &readSize);
if (res != kIOReturnSuccess)
@ -88,8 +75,7 @@ class HIDDeviceIOKit : public IHIDDevice
return 0;
}
static void _threadProcUSBLL(std::shared_ptr<HIDDeviceIOKit> device)
{
static void _threadProcUSBLL(std::shared_ptr<HIDDeviceIOKit> device) {
char thrName[128];
snprintf(thrName, 128, "%s Transfer Thread", device->m_token.getProductName().data());
pthread_setname_np(thrName);
@ -98,22 +84,18 @@ class HIDDeviceIOKit : public IHIDDevice
/* Get the HID element's parent (USB interrupt transfer-interface) */
IOObjectPointer<io_iterator_t> devIter;
IOObjectPointer<io_registry_entry_t> devEntry = IORegistryEntryFromPath(kIOMasterPortDefault,
device->m_devPath.data());
IOObjectPointer<io_registry_entry_t> devEntry =
IORegistryEntryFromPath(kIOMasterPortDefault, device->m_devPath.data());
IOObjectPointer<io_object_t> interfaceEntry;
IORegistryEntryGetChildIterator(devEntry.get(), kIOServicePlane, &devIter);
while (IOObjectPointer<io_service_t> obj = IOIteratorNext(devIter.get()))
{
if (IOObjectConformsTo(obj.get(), kIOUSBInterfaceClassName))
{
while (IOObjectPointer<io_service_t> obj = IOIteratorNext(devIter.get())) {
if (IOObjectConformsTo(obj.get(), kIOUSBInterfaceClassName)) {
interfaceEntry = obj;
break;
}
}
if (!interfaceEntry)
{
snprintf(errStr, 256, "Unable to find interface for %s@%s\n",
device->m_token.getProductName().data(),
if (!interfaceEntry) {
snprintf(errStr, 256, "Unable to find interface for %s@%s\n", device->m_token.getProductName().data(),
device->m_devPath.data());
device->m_devImp->deviceError(errStr);
lk.unlock();
@ -125,15 +107,11 @@ class HIDDeviceIOKit : public IHIDDevice
IOCFPluginPointer iodev;
SInt32 score;
IOReturn err;
err = IOCreatePlugInInterfaceForService(interfaceEntry.get(),
kIOUSBInterfaceUserClientTypeID,
kIOCFPlugInInterfaceID,
&iodev,
&score);
if (err)
{
snprintf(errStr, 256, "Unable to open %s@%s\n",
device->m_token.getProductName().data(), device->m_devPath.data());
err = IOCreatePlugInInterfaceForService(interfaceEntry.get(), kIOUSBInterfaceUserClientTypeID,
kIOCFPlugInInterfaceID, &iodev, &score);
if (err) {
snprintf(errStr, 256, "Unable to open %s@%s\n", device->m_token.getProductName().data(),
device->m_devPath.data());
device->m_devImp->deviceError(errStr);
lk.unlock();
device->m_initCond.notify_one();
@ -143,10 +121,9 @@ class HIDDeviceIOKit : public IHIDDevice
/* USB interface function-pointer table */
IUnknownPointer<IOUSBInterfaceInterface> intf;
err = iodev.As(&intf, kIOUSBInterfaceInterfaceID);
if (err)
{
snprintf(errStr, 256, "Unable to open %s@%s\n",
device->m_token.getProductName().data(), device->m_devPath.data());
if (err) {
snprintf(errStr, 256, "Unable to open %s@%s\n", device->m_token.getProductName().data(),
device->m_devPath.data());
device->m_devImp->deviceError(errStr);
lk.unlock();
device->m_initCond.notify_one();
@ -156,18 +133,14 @@ class HIDDeviceIOKit : public IHIDDevice
/* Obtain exclusive lock on device */
device->m_usbIntf = intf;
err = intf->USBInterfaceOpen(intf.storage());
if (err != kIOReturnSuccess)
{
if (err == kIOReturnExclusiveAccess)
{
snprintf(errStr, 256, "Unable to open %s@%s: someone else using it\n",
device->m_token.getProductName().data(), device->m_devPath.data());
if (err != kIOReturnSuccess) {
if (err == kIOReturnExclusiveAccess) {
snprintf(errStr, 256, "Unable to open %s@%s: someone else using it\n", device->m_token.getProductName().data(),
device->m_devPath.data());
device->m_devImp->deviceError(errStr);
}
else
{
snprintf(errStr, 256, "Unable to open %s@%s\n",
device->m_token.getProductName().data(), device->m_devPath.data());
} else {
snprintf(errStr, 256, "Unable to open %s@%s\n", device->m_token.getProductName().data(),
device->m_devPath.data());
device->m_devImp->deviceError(errStr);
}
lk.unlock();
@ -178,13 +151,11 @@ class HIDDeviceIOKit : public IHIDDevice
/* Determine pipe indices for interrupt I/O */
UInt8 numEndpoints = 0;
err = intf->GetNumEndpoints(intf.storage(), &numEndpoints);
for (int i=1 ; i<numEndpoints+1 ; ++i)
{
for (int i = 1; i < numEndpoints + 1; ++i) {
UInt8 dir, num, tType, interval;
UInt16 mPacketSz;
err = intf->GetPipeProperties(intf.storage(), i, &dir, &num, &tType, &mPacketSz, &interval);
if (tType == kUSBInterrupt)
{
if (tType == kUSBInterrupt) {
if (dir == kUSBIn)
device->m_usbIntfInPipe = num;
else if (dir == kUSBOut)
@ -208,8 +179,7 @@ class HIDDeviceIOKit : public IHIDDevice
device->m_usbIntf = nullptr;
}
static void _threadProcBTLL(std::shared_ptr<HIDDeviceIOKit> device)
{
static void _threadProcBTLL(std::shared_ptr<HIDDeviceIOKit> device) {
std::unique_lock<std::mutex> lk(device->m_initMutex);
/* Return control to main thread */
@ -224,26 +194,16 @@ class HIDDeviceIOKit : public IHIDDevice
device->m_devImp->finalCycle();
}
static void _hidRemoveCb(void * _Nullable context,
IOReturn result,
void * _Nullable sender)
{
static void _hidRemoveCb(void* _Nullable context, IOReturn result, void* _Nullable sender) {
reinterpret_cast<HIDDeviceIOKit*>(context)->m_runningTransferLoop = false;
}
static void _hidReportCb(void * _Nullable context,
IOReturn,
void * _Nullable,
IOHIDReportType type,
uint32_t reportID,
uint8_t * report,
CFIndex reportLength)
{
static void _hidReportCb(void* _Nullable context, IOReturn, void* _Nullable, IOHIDReportType type, uint32_t reportID,
uint8_t* report, CFIndex reportLength) {
reinterpret_cast<DeviceBase*>(context)->receivedHIDReport(report, reportLength, HIDReportType(type), reportID);
}
static void _threadProcHID(std::shared_ptr<HIDDeviceIOKit> device)
{
static void _threadProcHID(std::shared_ptr<HIDDeviceIOKit> device) {
char thrName[128];
snprintf(thrName, 128, "%s Transfer Thread", device->m_token.getProductName().data());
pthread_setname_np(thrName);
@ -253,10 +213,8 @@ class HIDDeviceIOKit : public IHIDDevice
/* Get the HID element's object (HID device interface) */
IOObjectPointer<io_service_t> interfaceEntry =
IORegistryEntryFromPath(kIOMasterPortDefault, device->m_devPath.data());
if (!IOObjectConformsTo(interfaceEntry.get(), "IOHIDDevice"))
{
snprintf(errStr, 256, "Unable to find interface for %s@%s\n",
device->m_token.getProductName().data(),
if (!IOObjectConformsTo(interfaceEntry.get(), "IOHIDDevice")) {
snprintf(errStr, 256, "Unable to find interface for %s@%s\n", device->m_token.getProductName().data(),
device->m_devPath.data());
device->m_devImp->deviceError(errStr);
lk.unlock();
@ -265,10 +223,9 @@ class HIDDeviceIOKit : public IHIDDevice
}
device->m_hidIntf = IOHIDDeviceCreate(nullptr, interfaceEntry.get());
if (!device->m_hidIntf)
{
snprintf(errStr, 256, "Unable to open %s@%s\n",
device->m_token.getProductName().data(), device->m_devPath.data());
if (!device->m_hidIntf) {
snprintf(errStr, 256, "Unable to open %s@%s\n", device->m_token.getProductName().data(),
device->m_devPath.data());
device->m_devImp->deviceError(errStr);
lk.unlock();
device->m_initCond.notify_one();
@ -277,18 +234,14 @@ class HIDDeviceIOKit : public IHIDDevice
/* Open device */
IOReturn err = IOHIDDeviceOpen(device->m_hidIntf.get(), kIOHIDOptionsTypeNone);
if (err != kIOReturnSuccess)
{
if (err == kIOReturnExclusiveAccess)
{
snprintf(errStr, 256, "Unable to open %s@%s: someone else using it\n",
device->m_token.getProductName().data(), device->m_devPath.data());
if (err != kIOReturnSuccess) {
if (err == kIOReturnExclusiveAccess) {
snprintf(errStr, 256, "Unable to open %s@%s: someone else using it\n", device->m_token.getProductName().data(),
device->m_devPath.data());
device->m_devImp->deviceError(errStr);
}
else
{
snprintf(errStr, 256, "Unable to open %s@%s\n",
device->m_token.getProductName().data(), device->m_devPath.data());
} else {
snprintf(errStr, 256, "Unable to open %s@%s\n", device->m_token.getProductName().data(),
device->m_devPath.data());
device->m_devImp->deviceError(errStr);
}
lk.unlock();
@ -301,18 +254,18 @@ class HIDDeviceIOKit : public IHIDDevice
/* Make note if device uses bluetooth driver */
if (CFTypeRef transport = IOHIDDeviceGetProperty(device->m_hidIntf.get(), CFSTR(kIOHIDTransportKey)))
device->m_isBt = CFStringCompare(CFStringRef(transport), CFSTR(kIOHIDTransportBluetoothValue), 0) == kCFCompareEqualTo;
device->m_isBt =
CFStringCompare(CFStringRef(transport), CFSTR(kIOHIDTransportBluetoothValue), 0) == kCFCompareEqualTo;
/* Register input buffer */
std::unique_ptr<uint8_t[]> buffer;
int bufSize = 0;
if (CFTypeRef maxSize = IOHIDDeviceGetProperty(device->m_hidIntf.get(), CFSTR(kIOHIDMaxInputReportSizeKey)))
CFNumberGetValue(CFNumberRef(maxSize), kCFNumberIntType, &bufSize);
if (bufSize)
{
if (bufSize) {
buffer = std::unique_ptr<uint8_t[]>(new uint8_t[bufSize]);
IOHIDDeviceRegisterInputReportCallback(device->m_hidIntf.get(), buffer.get(), bufSize,
_hidReportCb, device->m_devImp.get());
IOHIDDeviceRegisterInputReportCallback(device->m_hidIntf.get(), buffer.get(), bufSize, _hidReportCb,
device->m_devImp.get());
IOHIDDeviceScheduleWithRunLoop(device->m_hidIntf.get(), CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
}
@ -323,8 +276,7 @@ class HIDDeviceIOKit : public IHIDDevice
/* Start transfer loop */
device->m_devImp->initialCycle();
while (device->m_runningTransferLoop)
{
while (device->m_runningTransferLoop) {
CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.010, true);
if (device->m_runningTransferLoop)
device->m_devImp->transferCycle();
@ -336,22 +288,13 @@ class HIDDeviceIOKit : public IHIDDevice
device->m_hidIntf.reset();
}
void _deviceDisconnected()
{
m_runningTransferLoop = false;
}
void _deviceDisconnected() { m_runningTransferLoop = false; }
public:
HIDDeviceIOKit(DeviceToken& token, const std::shared_ptr<DeviceBase>& devImp)
: m_token(token),
m_devImp(devImp),
m_devPath(token.getDevicePath())
{
}
: m_token(token), m_devImp(devImp), m_devPath(token.getDevicePath()) {}
void _startThread()
{
void _startThread() {
std::unique_lock<std::mutex> lk(m_initMutex);
DeviceType dType = m_token.getDeviceType();
if (dType == DeviceType::USB)
@ -360,25 +303,22 @@ public:
m_thread = std::thread(_threadProcBTLL, std::static_pointer_cast<HIDDeviceIOKit>(shared_from_this()));
else if (dType == DeviceType::HID)
m_thread = std::thread(_threadProcHID, std::static_pointer_cast<HIDDeviceIOKit>(shared_from_this()));
else
{
else {
fprintf(stderr, "invalid token supplied to device constructor\n");
return;
}
m_initCond.wait(lk);
}
~HIDDeviceIOKit()
{
~HIDDeviceIOKit() {
m_runningTransferLoop = false;
if (m_thread.joinable())
m_thread.detach();
}
};
std::shared_ptr<IHIDDevice> IHIDDeviceNew(DeviceToken& token, const std::shared_ptr<DeviceBase>& devImp)
{
std::shared_ptr<IHIDDevice> IHIDDeviceNew(DeviceToken& token, const std::shared_ptr<DeviceBase>& devImp) {
return std::make_shared<HIDDeviceIOKit>(token, devImp);
}
}
} // namespace boo

View File

@ -1,21 +1,15 @@
#include "IHIDDevice.hpp"
namespace boo
{
namespace boo {
class HIDDeviceNX : public IHIDDevice
{
class HIDDeviceNX : public IHIDDevice {
DeviceToken& m_token;
std::shared_ptr<DeviceBase> m_devImp;
std::string_view m_devPath;
public:
HIDDeviceNX(DeviceToken& token, const std::shared_ptr<DeviceBase>& devImp)
: m_token(token),
m_devImp(devImp),
m_devPath(token.getDevicePath())
{
}
: m_token(token), m_devImp(devImp), m_devPath(token.getDevicePath()) {}
void _deviceDisconnected() {}
bool _sendUSBInterruptTransfer(const uint8_t* data, size_t length) { return false; }
@ -26,9 +20,8 @@ public:
void _startThread() {}
};
std::shared_ptr<IHIDDevice> IHIDDeviceNew(DeviceToken& token, const std::shared_ptr<DeviceBase>& devImp)
{
std::shared_ptr<IHIDDevice> IHIDDeviceNew(DeviceToken& token, const std::shared_ptr<DeviceBase>& devImp) {
return std::make_shared<HIDDeviceNX>(token, devImp);
}
}
} // namespace boo

View File

@ -3,16 +3,11 @@
#include "boo/inputdev/DeviceToken.hpp"
#include "boo/inputdev/DeviceBase.hpp"
namespace boo
{
namespace boo {
class HIDDeviceUWP : public IHIDDevice
{
class HIDDeviceUWP : public IHIDDevice {
public:
HIDDeviceUWP(DeviceToken& token, const std::shared_ptr<DeviceBase>& devImp)
{
}
HIDDeviceUWP(DeviceToken& token, const std::shared_ptr<DeviceBase>& devImp) {}
void _deviceDisconnected() {}
bool _sendUSBInterruptTransfer(const uint8_t* data, size_t length) { return false; }
@ -22,9 +17,8 @@ public:
void _startThread() {}
};
std::shared_ptr<IHIDDevice> IHIDDeviceNew(DeviceToken& token, const std::shared_ptr<DeviceBase>& devImp)
{
std::shared_ptr<IHIDDevice> IHIDDeviceNew(DeviceToken& token, const std::shared_ptr<DeviceBase>& devImp) {
return std::make_shared<HIDDeviceUWP>(token, devImp);
}
}
} // namespace boo

View File

@ -18,8 +18,7 @@
#include <cstring>
#include "boo/inputdev/HIDParser.hpp"
namespace boo
{
namespace boo {
udev* GetUdev();
@ -27,8 +26,7 @@ udev* GetUdev();
* Reference: http://tali.admingilde.org/linux-docbook/usb/ch07s06.html
*/
class HIDDeviceUdev final : public IHIDDevice
{
class HIDDeviceUdev final : public IHIDDevice {
DeviceToken& m_token;
std::shared_ptr<DeviceBase> m_devImp;
@ -42,17 +40,9 @@ class HIDDeviceUdev final : public IHIDDevice
std::condition_variable m_initCond;
std::thread m_thread;
bool _sendUSBInterruptTransfer(const uint8_t* data, size_t length)
{
if (m_devFd)
{
usbdevfs_bulktransfer xfer =
{
m_usbIntfOutPipe | USB_DIR_OUT,
(unsigned)length,
30,
(void*)data
};
bool _sendUSBInterruptTransfer(const uint8_t* data, size_t length) {
if (m_devFd) {
usbdevfs_bulktransfer xfer = {m_usbIntfOutPipe | USB_DIR_OUT, (unsigned)length, 30, (void*)data};
int ret = ioctl(m_devFd, USBDEVFS_BULK, &xfer);
if (ret != (int)length)
return false;
@ -61,24 +51,15 @@ class HIDDeviceUdev final : public IHIDDevice
return false;
}
size_t _receiveUSBInterruptTransfer(uint8_t* data, size_t length)
{
if (m_devFd)
{
usbdevfs_bulktransfer xfer =
{
m_usbIntfInPipe | USB_DIR_IN,
(unsigned)length,
30,
data
};
size_t _receiveUSBInterruptTransfer(uint8_t* data, size_t length) {
if (m_devFd) {
usbdevfs_bulktransfer xfer = {m_usbIntfInPipe | USB_DIR_IN, (unsigned)length, 30, data};
return ioctl(m_devFd, USBDEVFS_BULK, &xfer);
}
return 0;
}
static void _threadProcUSBLL(std::shared_ptr<HIDDeviceUdev> device)
{
static void _threadProcUSBLL(std::shared_ptr<HIDDeviceUdev> device) {
int i;
char errStr[256];
std::unique_lock<std::mutex> lk(device->m_initMutex);
@ -87,10 +68,8 @@ class HIDDeviceUdev final : public IHIDDevice
/* Get device file */
const char* dp = udev_device_get_devnode(udevDev);
int fd = open(dp, O_RDWR);
if (fd < 0)
{
snprintf(errStr, 256, "Unable to open %s@%s: %s\n",
device->m_token.getProductName().data(), dp, strerror(errno));
if (fd < 0) {
snprintf(errStr, 256, "Unable to open %s@%s: %s\n", device->m_token.getProductName().data(), dp, strerror(errno));
device->m_devImp->deviceError(errStr);
lk.unlock();
device->m_initCond.notify_one();
@ -101,23 +80,19 @@ class HIDDeviceUdev final : public IHIDDevice
usb_device_descriptor devDesc = {};
read(fd, &devDesc, 1);
read(fd, &devDesc.bDescriptorType, devDesc.bLength - 1);
if (devDesc.bNumConfigurations)
{
if (devDesc.bNumConfigurations) {
usb_config_descriptor confDesc = {};
read(fd, &confDesc, 1);
read(fd, &confDesc.bDescriptorType, confDesc.bLength - 1);
if (confDesc.bNumInterfaces)
{
if (confDesc.bNumInterfaces) {
usb_interface_descriptor intfDesc = {};
read(fd, &intfDesc, 1);
read(fd, &intfDesc.bDescriptorType, intfDesc.bLength - 1);
for (i=0 ; i<intfDesc.bNumEndpoints+1 ; ++i)
{
for (i = 0; i < intfDesc.bNumEndpoints + 1; ++i) {
usb_endpoint_descriptor endpDesc = {};
read(fd, &endpDesc, 1);
read(fd, &endpDesc.bDescriptorType, endpDesc.bLength - 1);
if ((endpDesc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)
{
if ((endpDesc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT) {
if ((endpDesc.bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN)
device->m_usbIntfInPipe = endpDesc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
else if ((endpDesc.bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT)
@ -128,11 +103,7 @@ class HIDDeviceUdev final : public IHIDDevice
}
/* Request that kernel disconnects existing driver */
usbdevfs_ioctl disconnectReq = {
0,
USBDEVFS_DISCONNECT,
NULL
};
usbdevfs_ioctl disconnectReq = {0, USBDEVFS_DISCONNECT, NULL};
ioctl(fd, USBDEVFS_IOCTL, &disconnectReq);
/* Return control to main thread */
@ -152,8 +123,7 @@ class HIDDeviceUdev final : public IHIDDevice
udev_device_unref(udevDev);
}
static void _threadProcBTLL(std::shared_ptr<HIDDeviceUdev> device)
{
static void _threadProcBTLL(std::shared_ptr<HIDDeviceUdev> device) {
std::unique_lock<std::mutex> lk(device->m_initMutex);
udev_device* udevDev = udev_device_new_from_syspath(GetUdev(), device->m_devPath.data());
@ -171,8 +141,7 @@ class HIDDeviceUdev final : public IHIDDevice
udev_device_unref(udevDev);
}
static void _threadProcHID(std::shared_ptr<HIDDeviceUdev> device)
{
static void _threadProcHID(std::shared_ptr<HIDDeviceUdev> device) {
char errStr[256];
std::unique_lock<std::mutex> lk(device->m_initMutex);
udev_device* udevDev = udev_device_new_from_syspath(GetUdev(), device->m_devPath.data());
@ -180,10 +149,8 @@ class HIDDeviceUdev final : public IHIDDevice
/* Get device file */
const char* dp = udev_device_get_devnode(udevDev);
int fd = open(dp, O_RDWR | O_NONBLOCK);
if (fd < 0)
{
snprintf(errStr, 256, "Unable to open %s@%s: %s\n",
device->m_token.getProductName().data(), dp, strerror(errno));
if (fd < 0) {
snprintf(errStr, 256, "Unable to open %s@%s: %s\n", device->m_token.getProductName().data(), dp, strerror(errno));
device->m_devImp->deviceError(errStr);
lk.unlock();
device->m_initCond.notify_one();
@ -199,10 +166,9 @@ class HIDDeviceUdev final : public IHIDDevice
/* Report descriptor size */
int reportDescSize;
if (ioctl(fd, HIDIOCGRDESCSIZE, &reportDescSize) == -1)
{
snprintf(errStr, 256, "Unable to ioctl(HIDIOCGRDESCSIZE) %s@%s: %s\n",
device->m_token.getProductName().data(), dp, strerror(errno));
if (ioctl(fd, HIDIOCGRDESCSIZE, &reportDescSize) == -1) {
snprintf(errStr, 256, "Unable to ioctl(HIDIOCGRDESCSIZE) %s@%s: %s\n", device->m_token.getProductName().data(),
dp, strerror(errno));
device->m_devImp->deviceError(errStr);
close(fd);
return;
@ -211,10 +177,9 @@ class HIDDeviceUdev final : public IHIDDevice
/* Get report descriptor */
hidraw_report_descriptor reportDesc;
reportDesc.size = reportDescSize;
if (ioctl(fd, HIDIOCGRDESC, &reportDesc) == -1)
{
snprintf(errStr, 256, "Unable to ioctl(HIDIOCGRDESC) %s@%s: %s\n",
device->m_token.getProductName().data(), dp, strerror(errno));
if (ioctl(fd, HIDIOCGRDESC, &reportDesc) == -1) {
snprintf(errStr, 256, "Unable to ioctl(HIDIOCGRDESC) %s@%s: %s\n", device->m_token.getProductName().data(), dp,
strerror(errno));
device->m_devImp->deviceError(errStr);
close(fd);
return;
@ -224,21 +189,17 @@ class HIDDeviceUdev final : public IHIDDevice
/* Start transfer loop */
device->m_devImp->initialCycle();
while (device->m_runningTransferLoop)
{
while (device->m_runningTransferLoop) {
fd_set readset;
FD_ZERO(&readset);
FD_SET(fd, &readset);
struct timeval timeout = {0, 10000};
if (select(fd + 1, &readset, nullptr, nullptr, &timeout) > 0)
{
while (true)
{
if (select(fd + 1, &readset, nullptr, nullptr, &timeout) > 0) {
while (true) {
ssize_t sz = read(fd, readBuf.get(), readSz);
if (sz < 0)
break;
device->m_devImp->receivedHIDReport(readBuf.get(), sz,
HIDReportType::Input, readBuf[0]);
device->m_devImp->receivedHIDReport(readBuf.get(), sz, HIDReportType::Input, readBuf[0]);
}
}
if (device->m_runningTransferLoop)
@ -252,13 +213,9 @@ class HIDDeviceUdev final : public IHIDDevice
udev_device_unref(udevDev);
}
void _deviceDisconnected()
{
m_runningTransferLoop = false;
}
void _deviceDisconnected() { m_runningTransferLoop = false; }
std::vector<uint8_t> _getReportDescriptor()
{
std::vector<uint8_t> _getReportDescriptor() {
/* Report descriptor size */
int reportDescSize;
if (ioctl(m_devFd, HIDIOCGRDESCSIZE, &reportDescSize) == -1)
@ -274,19 +231,14 @@ class HIDDeviceUdev final : public IHIDDevice
return ret;
}
bool _sendHIDReport(const uint8_t* data, size_t length, HIDReportType tp, uint32_t message)
{
if (m_devFd)
{
if (tp == HIDReportType::Feature)
{
bool _sendHIDReport(const uint8_t* data, size_t length, HIDReportType tp, uint32_t message) {
if (m_devFd) {
if (tp == HIDReportType::Feature) {
int ret = ioctl(m_devFd, HIDIOCSFEATURE(length), data);
if (ret < 0)
return false;
return true;
}
else if (tp == HIDReportType::Output)
{
} else if (tp == HIDReportType::Output) {
ssize_t ret = write(m_devFd, data, length);
if (ret < 0)
return false;
@ -296,12 +248,9 @@ class HIDDeviceUdev final : public IHIDDevice
return false;
}
size_t _receiveHIDReport(uint8_t *data, size_t length, HIDReportType tp, uint32_t message)
{
if (m_devFd)
{
if (tp == HIDReportType::Feature)
{
size_t _receiveHIDReport(uint8_t* data, size_t length, HIDReportType tp, uint32_t message) {
if (m_devFd) {
if (tp == HIDReportType::Feature) {
data[0] = message;
int ret = ioctl(m_devFd, HIDIOCGFEATURE(length), data);
if (ret < 0)
@ -313,16 +262,10 @@ class HIDDeviceUdev final : public IHIDDevice
}
public:
HIDDeviceUdev(DeviceToken& token, const std::shared_ptr<DeviceBase>& devImp)
: m_token(token),
m_devImp(devImp),
m_devPath(token.getDevicePath())
{
}
: m_token(token), m_devImp(devImp), m_devPath(token.getDevicePath()) {}
void _startThread()
{
void _startThread() {
std::unique_lock<std::mutex> lk(m_initMutex);
DeviceType dType = m_token.getDeviceType();
if (dType == DeviceType::USB)
@ -331,27 +274,22 @@ public:
m_thread = std::thread(_threadProcBTLL, std::static_pointer_cast<HIDDeviceUdev>(shared_from_this()));
else if (dType == DeviceType::HID)
m_thread = std::thread(_threadProcHID, std::static_pointer_cast<HIDDeviceUdev>(shared_from_this()));
else
{
else {
fprintf(stderr, "invalid token supplied to device constructor");
abort();
}
m_initCond.wait(lk);
}
~HIDDeviceUdev()
{
~HIDDeviceUdev() {
m_runningTransferLoop = false;
if (m_thread.joinable())
m_thread.detach();
}
};
std::shared_ptr<IHIDDevice> IHIDDeviceNew(DeviceToken& token, const std::shared_ptr<DeviceBase>& devImp)
{
std::shared_ptr<IHIDDevice> IHIDDeviceNew(DeviceToken& token, const std::shared_ptr<DeviceBase>& devImp) {
return std::make_shared<HIDDeviceUdev>(token, devImp);
}
}
} // namespace boo

View File

@ -21,11 +21,9 @@
#undef min
#undef max
namespace boo
{
namespace boo {
class HIDDeviceWinUSB final : public IHIDDevice
{
class HIDDeviceWinUSB final : public IHIDDevice {
DeviceToken& m_token;
std::shared_ptr<DeviceBase> m_devImp;
@ -41,13 +39,10 @@ class HIDDeviceWinUSB final : public IHIDDevice
std::condition_variable m_initCond;
std::thread m_thread;
bool _sendUSBInterruptTransfer(const uint8_t* data, size_t length)
{
if (m_usbHandle)
{
bool _sendUSBInterruptTransfer(const uint8_t* data, size_t length) {
if (m_usbHandle) {
ULONG lengthTransferred = 0;
if (!WinUsb_WritePipe(m_usbHandle, m_usbIntfOutPipe, (PUCHAR)data,
(ULONG)length, &lengthTransferred, NULL) ||
if (!WinUsb_WritePipe(m_usbHandle, m_usbIntfOutPipe, (PUCHAR)data, (ULONG)length, &lengthTransferred, NULL) ||
lengthTransferred != length)
return false;
return true;
@ -55,37 +50,27 @@ class HIDDeviceWinUSB final : public IHIDDevice
return false;
}
size_t _receiveUSBInterruptTransfer(uint8_t* data, size_t length)
{
if (m_usbHandle)
{
size_t _receiveUSBInterruptTransfer(uint8_t* data, size_t length) {
if (m_usbHandle) {
ULONG lengthTransferred = 0;
if (!WinUsb_ReadPipe(m_usbHandle, m_usbIntfInPipe, (PUCHAR)data,
(ULONG)length, &lengthTransferred, NULL))
if (!WinUsb_ReadPipe(m_usbHandle, m_usbIntfInPipe, (PUCHAR)data, (ULONG)length, &lengthTransferred, NULL))
return 0;
return lengthTransferred;
}
return 0;
}
static void _threadProcUSBLL(std::shared_ptr<HIDDeviceWinUSB> device)
{
static void _threadProcUSBLL(std::shared_ptr<HIDDeviceWinUSB> device) {
unsigned i;
char errStr[256];
std::unique_lock<std::mutex> lk(device->m_initMutex);
/* POSIX.. who needs it?? -MS */
device->m_devHandle = CreateFileA(device->m_devPath.data(),
GENERIC_WRITE | GENERIC_READ,
FILE_SHARE_WRITE | FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
NULL);
if (INVALID_HANDLE_VALUE == device->m_devHandle)
{
_snprintf(errStr, 256, "Unable to open %s@%s: %d\n",
device->m_token.getProductName().data(),
device->m_devHandle =
CreateFileA(device->m_devPath.data(), GENERIC_WRITE | GENERIC_READ, FILE_SHARE_WRITE | FILE_SHARE_READ, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);
if (INVALID_HANDLE_VALUE == device->m_devHandle) {
_snprintf(errStr, 256, "Unable to open %s@%s: %d\n", device->m_token.getProductName().data(),
device->m_devPath.data(), GetLastError());
device->m_devImp->deviceError(errStr);
lk.unlock();
@ -93,10 +78,8 @@ class HIDDeviceWinUSB final : public IHIDDevice
return;
}
if (!WinUsb_Initialize(device->m_devHandle, &device->m_usbHandle))
{
_snprintf(errStr, 256, "Unable to open %s@%s: %d\n",
device->m_token.getProductName().data(),
if (!WinUsb_Initialize(device->m_devHandle, &device->m_usbHandle)) {
_snprintf(errStr, 256, "Unable to open %s@%s: %d\n", device->m_token.getProductName().data(),
device->m_devPath.data(), GetLastError());
device->m_devImp->deviceError(errStr);
lk.unlock();
@ -107,10 +90,8 @@ class HIDDeviceWinUSB final : public IHIDDevice
/* Enumerate device pipes */
USB_INTERFACE_DESCRIPTOR ifDesc = {0};
if (!WinUsb_QueryInterfaceSettings(device->m_usbHandle, 0, &ifDesc))
{
_snprintf(errStr, 256, "Unable to open %s@%s: %d\n",
device->m_token.getProductName().data(),
if (!WinUsb_QueryInterfaceSettings(device->m_usbHandle, 0, &ifDesc)) {
_snprintf(errStr, 256, "Unable to open %s@%s: %d\n", device->m_token.getProductName().data(),
device->m_devPath.data(), GetLastError());
device->m_devImp->deviceError(errStr);
lk.unlock();
@ -118,12 +99,10 @@ class HIDDeviceWinUSB final : public IHIDDevice
CloseHandle(device->m_devHandle);
return;
}
for (i=0 ; i<ifDesc.bNumEndpoints ; ++i)
{
for (i = 0; i < ifDesc.bNumEndpoints; ++i) {
WINUSB_PIPE_INFORMATION pipeDesc;
WinUsb_QueryPipe(device->m_usbHandle, 0, i, &pipeDesc);
if (pipeDesc.PipeType == UsbdPipeTypeInterrupt)
{
if (pipeDesc.PipeType == UsbdPipeTypeInterrupt) {
if (USB_ENDPOINT_DIRECTION_IN(pipeDesc.PipeId))
device->m_usbIntfInPipe = pipeDesc.PipeId;
else
@ -148,8 +127,7 @@ class HIDDeviceWinUSB final : public IHIDDevice
device->m_devHandle = 0;
}
static void _threadProcBTLL(std::shared_ptr<HIDDeviceWinUSB> device)
{
static void _threadProcBTLL(std::shared_ptr<HIDDeviceWinUSB> device) {
std::unique_lock<std::mutex> lk(device->m_initMutex);
/* Return control to main thread */
@ -170,24 +148,17 @@ class HIDDeviceWinUSB final : public IHIDDevice
PHIDP_PREPARSED_DATA m_preparsedData = nullptr;
static void _threadProcHID(std::shared_ptr<HIDDeviceWinUSB> device)
{
static void _threadProcHID(std::shared_ptr<HIDDeviceWinUSB> device) {
char errStr[256];
std::unique_lock<std::mutex> lk(device->m_initMutex);
/* POSIX.. who needs it?? -MS */
device->m_overlapped.hEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr);
device->m_hidHandle = CreateFileA(device->m_devPath.data(),
GENERIC_WRITE | GENERIC_READ,
FILE_SHARE_WRITE | FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
NULL);
if (INVALID_HANDLE_VALUE == device->m_hidHandle)
{
_snprintf(errStr, 256, "Unable to open %s@%s: %d\n",
device->m_token.getProductName().data(),
device->m_hidHandle =
CreateFileA(device->m_devPath.data(), GENERIC_WRITE | GENERIC_READ, FILE_SHARE_WRITE | FILE_SHARE_READ, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);
if (INVALID_HANDLE_VALUE == device->m_hidHandle) {
_snprintf(errStr, 256, "Unable to open %s@%s: %d\n", device->m_token.getProductName().data(),
device->m_devPath.data(), GetLastError());
device->m_devImp->deviceError(errStr);
lk.unlock();
@ -195,10 +166,8 @@ class HIDDeviceWinUSB final : public IHIDDevice
return;
}
if (!HidD_GetPreparsedData(device->m_hidHandle, &device->m_preparsedData))
{
_snprintf(errStr, 256, "Unable get preparsed data of %s@%s: %d\n",
device->m_token.getProductName().data(),
if (!HidD_GetPreparsedData(device->m_hidHandle, &device->m_preparsedData)) {
_snprintf(errStr, 256, "Unable get preparsed data of %s@%s: %d\n", device->m_token.getProductName().data(),
device->m_devPath.data(), GetLastError());
device->m_devImp->deviceError(errStr);
lk.unlock();
@ -223,8 +192,7 @@ class HIDDeviceWinUSB final : public IHIDDevice
/* Start transfer loop */
device->m_devImp->initialCycle();
while (device->m_runningTransferLoop)
{
while (device->m_runningTransferLoop) {
device->ReadCycle(readBuf.get(), inBufferSz);
if (device->m_runningTransferLoop)
device->m_devImp->transferCycle();
@ -238,21 +206,14 @@ class HIDDeviceWinUSB final : public IHIDDevice
device->m_hidHandle = nullptr;
}
void _deviceDisconnected()
{
m_runningTransferLoop = false;
}
void _deviceDisconnected() { m_runningTransferLoop = false; }
std::vector<uint8_t> m_sendBuf;
std::vector<uint8_t> m_recvBuf;
const PHIDP_PREPARSED_DATA _getReportDescriptor()
{
return m_preparsedData;
}
const PHIDP_PREPARSED_DATA _getReportDescriptor() { return m_preparsedData; }
bool _sendHIDReport(const uint8_t* data, size_t length, HIDReportType tp, uint32_t message)
{
bool _sendHIDReport(const uint8_t* data, size_t length, HIDReportType tp, uint32_t message) {
size_t maxOut = std::max(m_minFeatureSz, std::max(m_minOutputSz, length));
if (m_sendBuf.size() < maxOut)
m_sendBuf.resize(maxOut);
@ -260,43 +221,35 @@ class HIDDeviceWinUSB final : public IHIDDevice
memset(m_sendBuf.data() + length, 0, maxOut - length);
memmove(m_sendBuf.data(), data, length);
if (tp == HIDReportType::Output)
{
if (tp == HIDReportType::Output) {
DWORD useLength = DWORD(std::max(length, m_minOutputSz));
DWORD BytesWritten;
OVERLAPPED Overlapped;
ZeroMemory(&Overlapped, sizeof(Overlapped));
BOOL Result = WriteFile(m_hidHandle, m_sendBuf.data(), useLength, &BytesWritten, &Overlapped);
if (!Result)
{
if (!Result) {
DWORD Error = GetLastError();
if (Error == ERROR_INVALID_USER_BUFFER)
{
if (Error == ERROR_INVALID_USER_BUFFER) {
// std::cout << "Falling back to SetOutputReport" << std::endl;
if (!HidD_SetOutputReport(m_hidHandle, (PVOID)m_sendBuf.data(), useLength))
return false;
}
if (Error != ERROR_IO_PENDING)
{
if (Error != ERROR_IO_PENDING) {
fprintf(stderr, "Write Failed %08X\n", int(Error));
return false;
}
}
if (!GetOverlappedResult(m_hidHandle, &Overlapped, &BytesWritten, TRUE))
{
if (!GetOverlappedResult(m_hidHandle, &Overlapped, &BytesWritten, TRUE)) {
DWORD Error = GetLastError();
fprintf(stderr, "Write Failed %08X\n", int(Error));
return false;
}
}
else if (tp == HIDReportType::Feature)
{
} else if (tp == HIDReportType::Feature) {
DWORD useLength = DWORD(std::max(length, m_minFeatureSz));
if (!HidD_SetFeature(m_hidHandle, (PVOID)m_sendBuf.data(), useLength))
{
if (!HidD_SetFeature(m_hidHandle, (PVOID)m_sendBuf.data(), useLength)) {
// int error = GetLastError();
return false;
}
@ -304,22 +257,17 @@ class HIDDeviceWinUSB final : public IHIDDevice
return true;
}
size_t _receiveHIDReport(uint8_t* data, size_t length, HIDReportType tp, uint32_t message)
{
size_t _receiveHIDReport(uint8_t* data, size_t length, HIDReportType tp, uint32_t message) {
size_t maxIn = std::max(m_minFeatureSz, std::max(m_minInputSz, length));
if (m_recvBuf.size() < maxIn)
m_recvBuf.resize(maxIn);
memset(m_recvBuf.data(), 0, length);
m_recvBuf[0] = message;
if (tp == HIDReportType::Input)
{
if (tp == HIDReportType::Input) {
if (!HidD_GetInputReport(m_hidHandle, m_recvBuf.data(), ULONG(std::max(m_minInputSz, length))))
return 0;
}
else if (tp == HIDReportType::Feature)
{
} else if (tp == HIDReportType::Feature) {
if (!HidD_GetFeature(m_hidHandle, m_recvBuf.data(), ULONG(std::max(m_minFeatureSz, length))))
return 0;
}
@ -329,16 +277,10 @@ class HIDDeviceWinUSB final : public IHIDDevice
}
public:
HIDDeviceWinUSB(DeviceToken& token, const std::shared_ptr<DeviceBase>& devImp)
: m_token(token),
m_devImp(devImp),
m_devPath(token.getDevicePath())
{
}
: m_token(token), m_devImp(devImp), m_devPath(token.getDevicePath()) {}
void _startThread()
{
void _startThread() {
std::unique_lock<std::mutex> lk(m_initMutex);
DeviceType dType = m_token.getDeviceType();
if (dType == DeviceType::USB)
@ -352,8 +294,7 @@ public:
m_initCond.wait(lk);
}
~HIDDeviceWinUSB()
{
~HIDDeviceWinUSB() {
m_runningTransferLoop = false;
if (m_thread.joinable())
m_thread.detach();
@ -361,27 +302,20 @@ public:
OVERLAPPED m_overlapped = {};
void ReadCycle(uint8_t* inBuffer, size_t inBufferSz)
{
void ReadCycle(uint8_t* inBuffer, size_t inBufferSz) {
ResetEvent(m_overlapped.hEvent);
ZeroMemory(inBuffer, inBufferSz);
DWORD BytesRead = 0;
BOOL Result = ReadFile(m_hidHandle, inBuffer, DWORD(inBufferSz), &BytesRead, &m_overlapped);
if (!Result)
{
if (!Result) {
DWORD Error = GetLastError();
if (Error == ERROR_DEVICE_NOT_CONNECTED)
{
if (Error == ERROR_DEVICE_NOT_CONNECTED) {
m_runningTransferLoop = false;
return;
}
else if (Error != ERROR_IO_PENDING)
{
} else if (Error != ERROR_IO_PENDING) {
fprintf(stderr, "Read Failed: %08X\n", int(Error));
return;
}
else if (!GetOverlappedResultEx(m_hidHandle, &m_overlapped, &BytesRead, 10, TRUE))
{
} else if (!GetOverlappedResultEx(m_hidHandle, &m_overlapped, &BytesRead, 10, TRUE)) {
return;
}
}
@ -390,9 +324,8 @@ public:
}
};
std::shared_ptr<IHIDDevice> IHIDDeviceNew(DeviceToken& token, const std::shared_ptr<DeviceBase>& devImp)
{
std::shared_ptr<IHIDDevice> IHIDDeviceNew(DeviceToken& token, const std::shared_ptr<DeviceBase>& devImp) {
return std::make_shared<HIDDeviceWinUSB>(token, devImp);
}
}
} // namespace boo

View File

@ -2,11 +2,9 @@
#include "boo/inputdev/DeviceToken.hpp"
#include "boo/inputdev/DeviceBase.hpp"
namespace boo
{
namespace boo {
class HIDDeviceBSD final : public IHIDDevice
{
class HIDDeviceBSD final : public IHIDDevice {
DeviceToken& m_token;
DeviceBase& m_devImp;
@ -15,20 +13,14 @@ class HIDDeviceBSD final : public IHIDDevice
size_t _receiveUSBInterruptTransfer(uint8_t* data, size_t length) { return 0; }
bool _sendHIDReport(const uint8_t* data, size_t length, uint16_t message) { return false; }
size_t _recieveReport(const uint8_t* data, size_t length, uint16_t message) { return 0; }
public:
HIDDeviceBSD(DeviceToken& token, DeviceBase& devImp)
: m_token(token),
m_devImp(devImp)
{
}
~HIDDeviceBSD()
{
}
public:
HIDDeviceBSD(DeviceToken& token, DeviceBase& devImp) : m_token(token), m_devImp(devImp) {}
~HIDDeviceBSD() {}
};
std::shared_ptr<IHIDDevice> IHIDDeviceNew(DeviceToken& token, const std::shared_ptr<DeviceBase>& devImp)
{
std::shared_ptr<IHIDDevice> IHIDDeviceNew(DeviceToken& token, const std::shared_ptr<DeviceBase>& devImp) {
return std::make_shared<HIDDeviceBSD>(token, devImp);
}
}
} // namespace boo

View File

@ -11,24 +11,20 @@
#include "IOKitPointer.hpp"
#include "../CFPointer.hpp"
namespace boo
{
namespace boo {
/*
* Reference: http://oroboro.com/usb-serial-number-osx/
*/
static bool getUSBStringDescriptor(const IUnknownPointer<IOUSBDeviceInterface182>& usbDevice, UInt8 idx, char* out)
{
static bool getUSBStringDescriptor(const IUnknownPointer<IOUSBDeviceInterface182>& usbDevice, UInt8 idx, char* out) {
UInt16 buffer[128];
// wow... we're actually forced to make hard coded bus requests. Its like
// hard disk programming in the 80's!
IOUSBDevRequest request;
request.bmRequestType = USBmakebmRequestType(kUSBIn,
kUSBStandard,
kUSBDevice);
request.bmRequestType = USBmakebmRequestType(kUSBIn, kUSBStandard, kUSBDevice);
request.bRequest = kUSBRqGetDescriptor;
request.wValue = (kUSBStringDesc << 8) | idx;
request.wIndex = 0x409; // english
@ -36,8 +32,7 @@ static bool getUSBStringDescriptor(const IUnknownPointer<IOUSBDeviceInterface182
request.pData = buffer;
kern_return_t err = usbDevice->DeviceRequest(usbDevice.storage(), &request);
if (err != 0)
{
if (err != 0) {
// the request failed... fairly uncommon for the USB disk driver, but not
// so uncommon for other devices. This can also be less reliable if your
// disk is mounted through an external USB hub. At this level we actually
@ -60,8 +55,7 @@ static bool getUSBStringDescriptor(const IUnknownPointer<IOUSBDeviceInterface182
return true;
}
class HIDListenerIOKit : public IHIDListener
{
class HIDListenerIOKit : public IHIDListener {
DeviceFinder& m_finder;
CFRunLoopRef m_listenerRunLoop;
@ -71,17 +65,13 @@ class HIDListenerIOKit : public IHIDListener
const char* m_usbClass;
bool m_scanningEnabled;
static void devicesConnectedUSBLL(HIDListenerIOKit* listener,
io_iterator_t iterator)
{
while (IOObjectPointer<io_service_t> obj = IOIteratorNext(iterator))
{
static void devicesConnectedUSBLL(HIDListenerIOKit* listener, io_iterator_t iterator) {
while (IOObjectPointer<io_service_t> obj = IOIteratorNext(iterator)) {
io_string_t devPath;
if (IORegistryEntryGetPath(obj.get(), kIOServicePlane, devPath) != 0)
continue;
if (!listener->m_scanningEnabled ||
listener->m_finder._hasToken(devPath))
if (!listener->m_scanningEnabled || listener->m_finder._hasToken(devPath))
continue;
UInt16 vid, pid;
@ -91,17 +81,16 @@ class HIDListenerIOKit : public IHIDListener
IOCFPluginPointer devServ;
SInt32 score;
IOReturn err;
err = IOCreatePlugInInterfaceForService(obj.get(), kIOUSBDeviceUserClientTypeID, kIOCFPlugInInterfaceID, &devServ, &score);
if (err != kIOReturnSuccess)
{
err = IOCreatePlugInInterfaceForService(obj.get(), kIOUSBDeviceUserClientTypeID, kIOCFPlugInInterfaceID,
&devServ, &score);
if (err != kIOReturnSuccess) {
fprintf(stderr, "unable to open IOKit plugin interface\n");
continue;
}
IUnknownPointer<IOUSBDeviceInterface182> dev;
err = devServ.As(&dev, kIOUSBDeviceInterfaceID182);
if (err != kIOReturnSuccess)
{
if (err != kIOReturnSuccess) {
fprintf(stderr, "unable to open IOKit device interface\n");
continue;
}
@ -117,26 +106,20 @@ class HIDListenerIOKit : public IHIDListener
getUSBStringDescriptor(dev, pstridx, pstr);
}
listener->m_finder._insertToken(std::make_unique<DeviceToken>(DeviceType::USB,
vid, pid, vstr, pstr, devPath));
listener->m_finder._insertToken(std::make_unique<DeviceToken>(DeviceType::USB, vid, pid, vstr, pstr, devPath));
// printf("ADDED %08X %s\n", obj.get(), devPath);
}
}
static void devicesDisconnectedUSBLL(HIDListenerIOKit* listener,
io_iterator_t iterator)
{
if (CFRunLoopGetCurrent() != listener->m_listenerRunLoop)
{
CFRunLoopPerformBlock(listener->m_listenerRunLoop, kCFRunLoopDefaultMode, ^{
devicesDisconnectedUSBLL(listener, iterator);
});
static void devicesDisconnectedUSBLL(HIDListenerIOKit* listener, io_iterator_t iterator) {
if (CFRunLoopGetCurrent() != listener->m_listenerRunLoop) {
CFRunLoopPerformBlock(listener->m_listenerRunLoop, kCFRunLoopDefaultMode,
^{ devicesDisconnectedUSBLL(listener, iterator); });
CFRunLoopWakeUp(listener->m_listenerRunLoop);
return;
}
while (IOObjectPointer<io_service_t> obj = IOIteratorNext(iterator))
{
while (IOObjectPointer<io_service_t> obj = IOIteratorNext(iterator)) {
io_string_t devPath;
if (IORegistryEntryGetPath(obj.get(), kIOServicePlane, devPath) != 0)
continue;
@ -145,17 +128,13 @@ class HIDListenerIOKit : public IHIDListener
}
}
static void devicesConnectedHID(HIDListenerIOKit* listener,
io_iterator_t iterator)
{
while (IOObjectPointer<io_service_t> obj = IOIteratorNext(iterator))
{
static void devicesConnectedHID(HIDListenerIOKit* listener, io_iterator_t iterator) {
while (IOObjectPointer<io_service_t> obj = IOIteratorNext(iterator)) {
io_string_t devPath;
if (IORegistryEntryGetPath(obj.get(), kIOServicePlane, devPath) != 0)
continue;
if (!listener->m_scanningEnabled ||
listener->m_finder._hasToken(devPath))
if (!listener->m_scanningEnabled || listener->m_finder._hasToken(devPath))
continue;
unsigned vidv, pidv;
@ -165,17 +144,16 @@ class HIDListenerIOKit : public IHIDListener
IOCFPluginPointer devServ;
SInt32 score;
IOReturn err;
err = IOCreatePlugInInterfaceForService(obj.get(), kIOHIDDeviceTypeID, kIOCFPlugInInterfaceID, &devServ, &score);
if (err != kIOReturnSuccess)
{
err =
IOCreatePlugInInterfaceForService(obj.get(), kIOHIDDeviceTypeID, kIOCFPlugInInterfaceID, &devServ, &score);
if (err != kIOReturnSuccess) {
fprintf(stderr, "unable to open IOKit plugin interface\n");
continue;
}
IUnknownPointer<IOHIDDeviceDeviceInterface> dev;
err = devServ.As(&dev, kIOHIDDeviceDeviceInterfaceID);
if (err != kIOReturnSuccess)
{
if (err != kIOReturnSuccess) {
fprintf(stderr, "unable to open IOKit device interface\n");
continue;
}
@ -188,13 +166,10 @@ class HIDListenerIOKit : public IHIDListener
int usagePageV, usageV;
CFNumberGetValue(usagePage.get(), kCFNumberIntType, &usagePageV);
CFNumberGetValue(usage.get(), kCFNumberIntType, &usageV);
if (usagePageV == kHIDPage_GenericDesktop)
{
if (usagePageV == kHIDPage_GenericDesktop) {
if (usageV != kHIDUsage_GD_Joystick && usageV != kHIDUsage_GD_GamePad)
continue;
}
else
{
} else {
continue;
}
@ -214,26 +189,20 @@ class HIDListenerIOKit : public IHIDListener
CFStringGetCString(pstridx.get(), pstr, 128, kCFStringEncodingUTF8);
}
listener->m_finder._insertToken(std::make_unique<DeviceToken>(DeviceType::HID,
vidv, pidv, vstr, pstr, devPath));
listener->m_finder._insertToken(std::make_unique<DeviceToken>(DeviceType::HID, vidv, pidv, vstr, pstr, devPath));
// printf("ADDED %08X %s\n", obj, devPath);
}
}
static void devicesDisconnectedHID(HIDListenerIOKit* listener,
io_iterator_t iterator)
{
if (CFRunLoopGetCurrent() != listener->m_listenerRunLoop)
{
CFRunLoopPerformBlock(listener->m_listenerRunLoop, kCFRunLoopDefaultMode, ^{
devicesDisconnectedHID(listener, iterator);
});
static void devicesDisconnectedHID(HIDListenerIOKit* listener, io_iterator_t iterator) {
if (CFRunLoopGetCurrent() != listener->m_listenerRunLoop) {
CFRunLoopPerformBlock(listener->m_listenerRunLoop, kCFRunLoopDefaultMode,
^{ devicesDisconnectedHID(listener, iterator); });
CFRunLoopWakeUp(listener->m_listenerRunLoop);
return;
}
while (IOObjectPointer<io_service_t> obj = IOIteratorNext(iterator))
{
while (IOObjectPointer<io_service_t> obj = IOIteratorNext(iterator)) {
io_string_t devPath;
if (IORegistryEntryGetPath(obj.get(), kIOServicePlane, devPath) != 0)
continue;
@ -243,9 +212,7 @@ class HIDListenerIOKit : public IHIDListener
}
public:
HIDListenerIOKit(DeviceFinder& finder)
: m_finder(finder)
{
HIDListenerIOKit(DeviceFinder& finder) : m_finder(finder) {
struct utsname kernInfo;
uname(&kernInfo);
int release = atoi(kernInfo.release);
@ -296,41 +263,33 @@ public:
m_scanningEnabled = false;
}
~HIDListenerIOKit()
{
~HIDListenerIOKit() {
// CFRunLoopRemoveSource(m_listenerRunLoop, IONotificationPortGetRunLoopSource(m_llPort), kCFRunLoopDefaultMode);
IONotificationPortDestroy(m_llPort);
}
/* Automatic device scanning */
bool startScanning()
{
bool startScanning() {
m_scanningEnabled = true;
return true;
}
bool stopScanning()
{
bool stopScanning() {
m_scanningEnabled = false;
return true;
}
/* Manual device scanning */
bool scanNow()
{
bool scanNow() {
IOObjectPointer<io_iterator_t> iter;
if (IOServiceGetMatchingServices(kIOMasterPortDefault,
IOServiceMatching(m_usbClass), &iter) == kIOReturnSuccess)
{
if (IOServiceGetMatchingServices(kIOMasterPortDefault, IOServiceMatching(m_usbClass), &iter) == kIOReturnSuccess) {
devicesConnectedUSBLL(this, iter.get());
}
return true;
}
};
std::unique_ptr<IHIDListener> IHIDListenerNew(DeviceFinder& finder)
{
std::unique_ptr<IHIDListener> IHIDListenerNew(DeviceFinder& finder) {
return std::make_unique<HIDListenerIOKit>(finder);
}
}
} // namespace boo

View File

@ -1,25 +1,18 @@
#include "boo/inputdev/IHIDListener.hpp"
namespace boo
{
namespace boo {
class HIDListenerNX : public IHIDListener
{
class HIDListenerNX : public IHIDListener {
DeviceFinder& m_finder;
public:
HIDListenerNX(DeviceFinder& finder)
: m_finder(finder)
{}
HIDListenerNX(DeviceFinder& finder) : m_finder(finder) {}
bool startScanning() { return false; }
bool stopScanning() { return false; }
bool scanNow() { return false; }
};
std::unique_ptr<IHIDListener> IHIDListenerNew(DeviceFinder& finder)
{
return std::make_unique<HIDListenerNX>(finder);
}
std::unique_ptr<IHIDListener> IHIDListenerNew(DeviceFinder& finder) { return std::make_unique<HIDListenerNX>(finder); }
}
} // namespace boo

View File

@ -2,11 +2,9 @@
#include "boo/inputdev/IHIDListener.hpp"
#include "boo/inputdev/DeviceFinder.hpp"
namespace boo
{
namespace boo {
class HIDListenerUWP : public IHIDListener
{
class HIDListenerUWP : public IHIDListener {
public:
HIDListenerUWP(DeviceFinder& finder) {}
@ -18,9 +16,6 @@ public:
bool scanNow() { return false; }
};
std::unique_ptr<IHIDListener> IHIDListenerNew(DeviceFinder& finder)
{
return std::make_unique<HIDListenerUWP>(finder);
}
std::unique_ptr<IHIDListener> IHIDListenerNew(DeviceFinder& finder) { return std::make_unique<HIDListenerUWP>(finder); }
}
} // namespace boo

View File

@ -12,27 +12,23 @@
#include <unistd.h>
#include <thread>
namespace boo
{
namespace boo {
static udev* UDEV_INST = nullptr;
udev* GetUdev()
{
udev* GetUdev() {
if (!UDEV_INST)
UDEV_INST = udev_new();
return UDEV_INST;
}
class HIDListenerUdev final : public IHIDListener
{
class HIDListenerUdev final : public IHIDListener {
DeviceFinder& m_finder;
udev_monitor* m_udevMon;
std::thread m_udevThread;
bool m_scanningEnabled;
void deviceConnected(udev_device* device)
{
void deviceConnected(udev_device* device) {
if (!m_scanningEnabled)
return;
@ -47,8 +43,7 @@ class HIDListenerUdev final : public IHIDListener
int vid = 0, pid = 0;
const char* manuf = nullptr;
const char* product = nullptr;
if (dt)
{
if (dt) {
if (!strcmp(dt, "usb_device"))
type = DeviceType::USB;
else if (!strcmp(dt, "bluetooth_device"))
@ -72,16 +67,13 @@ class HIDListenerUdev final : public IHIDListener
udev_list_entry* producte = udev_list_entry_get_by_name(attrs, "ID_MODEL");
if (producte)
product = udev_list_entry_get_value(producte);
}
else if (!strcmp(udev_device_get_subsystem(device), "hidraw"))
{
} else if (!strcmp(udev_device_get_subsystem(device), "hidraw")) {
type = DeviceType::HID;
udev_device* parent = udev_device_get_parent(device);
udev_list_entry* attrs = udev_device_get_properties_list_entry(parent);
udev_list_entry* hidide = udev_list_entry_get_by_name(attrs, "HID_ID");
if (hidide)
{
if (hidide) {
const char* hidid = udev_list_entry_get_value(hidide);
const char* vids = strchr(hidid, ':') + 1;
const char* pids = strchr(vids, ':') + 1;
@ -90,8 +82,7 @@ class HIDListenerUdev final : public IHIDListener
}
udev_list_entry* hidnamee = udev_list_entry_get_by_name(attrs, "HID_NAME");
if (hidnamee)
{
if (hidnamee) {
product = udev_list_entry_get_value(hidnamee);
manuf = product;
}
@ -104,8 +95,7 @@ class HIDListenerUdev final : public IHIDListener
/* Report descriptor size */
int reportDescSize;
if (ioctl(fd, HIDIOCGRDESCSIZE, &reportDescSize) == -1)
{
if (ioctl(fd, HIDIOCGRDESCSIZE, &reportDescSize) == -1) {
// const char* err = strerror(errno);
close(fd);
return;
@ -114,16 +104,14 @@ class HIDListenerUdev final : public IHIDListener
/* Get report descriptor */
hidraw_report_descriptor reportDesc;
reportDesc.size = reportDescSize;
if (ioctl(fd, HIDIOCGRDESC, &reportDesc) == -1)
{
if (ioctl(fd, HIDIOCGRDESC, &reportDesc) == -1) {
// const char* err = strerror(errno);
close(fd);
return;
}
close(fd);
std::pair<HIDUsagePage, HIDUsage> usage =
HIDParser::GetApplicationUsage(reportDesc.value, reportDesc.size);
std::pair<HIDUsagePage, HIDUsage> usage = HIDParser::GetApplicationUsage(reportDesc.value, reportDesc.size);
if (usage.first != HIDUsagePage::GenericDesktop ||
(usage.second != HIDUsage::Joystick && usage.second != HIDUsage::GamePad))
return;
@ -143,24 +131,20 @@ class HIDListenerUdev final : public IHIDListener
m_finder._insertToken(std::make_unique<DeviceToken>(type, vid, pid, manuf, product, devPath));
}
void deviceDisconnected(udev_device* device)
{
void deviceDisconnected(udev_device* device) {
const char* devPath = udev_device_get_syspath(device);
m_finder._removeToken(devPath);
}
void _udevProc()
{
void _udevProc() {
logvisor::RegisterThreadName("Boo udev");
udev_monitor_enable_receiving(m_udevMon);
int fd = udev_monitor_get_fd(m_udevMon);
while (true)
{
while (true) {
fd_set fds;
FD_ZERO(&fds);
FD_SET(fd, &fds);
if (pselect(fd+1, &fds, nullptr, nullptr, nullptr, nullptr) < 0)
{
if (pselect(fd + 1, &fds, nullptr, nullptr, nullptr, nullptr) < 0) {
/* SIGTERM handled here */
if (errno == EINTR)
break;
@ -168,8 +152,7 @@ class HIDListenerUdev final : public IHIDListener
int oldtype;
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldtype);
udev_device* dev = udev_monitor_receive_device(m_udevMon);
if (dev)
{
if (dev) {
const char* action = udev_device_get_action(dev);
if (!strcmp(action, "add"))
deviceConnected(dev);
@ -183,13 +166,10 @@ class HIDListenerUdev final : public IHIDListener
}
public:
HIDListenerUdev(DeviceFinder& finder)
: m_finder(finder)
{
HIDListenerUdev(DeviceFinder& finder) : m_finder(finder) {
/* Setup hotplug events */
m_udevMon = udev_monitor_new_from_netlink(GetUdev(), "udev");
if (!m_udevMon)
{
if (!m_udevMon) {
fprintf(stderr, "unable to init udev_monitor");
abort();
}
@ -207,8 +187,7 @@ public:
m_udevThread = std::thread(std::bind(&HIDListenerUdev::_udevProc, this), this);
}
~HIDListenerUdev()
{
~HIDListenerUdev() {
pthread_cancel(m_udevThread.native_handle());
if (m_udevThread.joinable())
m_udevThread.join();
@ -216,20 +195,17 @@ public:
}
/* Automatic device scanning */
bool startScanning()
{
bool startScanning() {
m_scanningEnabled = true;
return true;
}
bool stopScanning()
{
bool stopScanning() {
m_scanningEnabled = false;
return true;
}
/* Manual device scanning */
bool scanNow()
{
bool scanNow() {
udev_enumerate* uenum = udev_enumerate_new(GetUdev());
udev_enumerate_add_match_subsystem(uenum, "usb");
udev_enumerate_add_match_subsystem(uenum, "bluetooth");
@ -237,8 +213,7 @@ public:
udev_enumerate_scan_devices(uenum);
udev_list_entry* uenumList = udev_enumerate_get_list_entry(uenum);
udev_list_entry* uenumItem;
udev_list_entry_foreach(uenumItem, uenumList)
{
udev_list_entry_foreach(uenumItem, uenumList) {
const char* devPath = udev_list_entry_get_name(uenumItem);
udev_device* dev = udev_device_new_from_syspath(UDEV_INST, devPath);
if (dev)
@ -248,12 +223,10 @@ public:
udev_enumerate_unref(uenum);
return true;
}
};
std::unique_ptr<IHIDListener> IHIDListenerNew(DeviceFinder& finder)
{
std::unique_ptr<IHIDListener> IHIDListenerNew(DeviceFinder& finder) {
return std::make_unique<HIDListenerUdev>(finder);
}
}
} // namespace boo

View File

@ -18,11 +18,9 @@
#include <hidclass.h>
#include <Xinput.h>
namespace boo
{
namespace boo {
class HIDListenerWinUSB final : public IHIDListener
{
class HIDListenerWinUSB final : public IHIDListener {
DeviceFinder& m_finder;
bool m_scanningEnabled;
@ -31,8 +29,7 @@ class HIDListenerWinUSB final : public IHIDListener
* Reference: https://github.com/pbatard/libwdi/blob/master/libwdi/libwdi.c
*/
void _enumerate(DeviceType type, CONST GUID* TypeGUID, const char* pathFilter)
{
void _enumerate(DeviceType type, CONST GUID* TypeGUID, const char* pathFilter) {
/* Don't ask */
static const LPCSTR arPrefix[3] = {"VID_", "PID_", "MI_"};
unsigned i, j;
@ -58,22 +55,13 @@ class HIDListenerWinUSB final : public IHIDListener
if (hDevInfo == INVALID_HANDLE_VALUE)
return;
for (i=0 ; ; ++i)
{
if (!SetupDiEnumDeviceInterfaces(hDevInfo,
NULL,
TypeGUID,
i,
&DeviceInterfaceData))
for (i = 0;; ++i) {
if (!SetupDiEnumDeviceInterfaces(hDevInfo, NULL, TypeGUID, i, &DeviceInterfaceData))
break;
DeviceInterfaceDetailData.wtf.cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
if (!SetupDiGetDeviceInterfaceDetailA(hDevInfo,
&DeviceInterfaceData,
&DeviceInterfaceDetailData.wtf,
sizeof(DeviceInterfaceDetailData),
NULL,
&DeviceInfoData))
if (!SetupDiGetDeviceInterfaceDetailA(hDevInfo, &DeviceInterfaceData, &DeviceInterfaceDetailData.wtf,
sizeof(DeviceInterfaceDetailData), NULL, &DeviceInfoData))
continue;
r = CM_Get_Device_IDA(DeviceInfoData.DevInst, szDeviceInstanceID, MAX_PATH, 0);
@ -85,14 +73,10 @@ class HIDListenerWinUSB final : public IHIDListener
szVid[0] = '\0';
szPid[0] = '\0';
szMi[0] = '\0';
while (pszToken != NULL)
{
for (j=0 ; j<3 ; ++j)
{
if (strncmp(pszToken, arPrefix[j], 4) == 0)
{
switch (j)
{
while (pszToken != NULL) {
for (j = 0; j < 3; ++j) {
if (strncmp(pszToken, arPrefix[j], 4) == 0) {
switch (j) {
case 0:
strcpy_s(szVid, MAX_DEVICE_ID_LEN, pszToken);
break;
@ -119,11 +103,11 @@ class HIDListenerWinUSB final : public IHIDListener
CHAR productW[1024] = {0};
// CHAR product[1024] = {0};
DWORD productSz = 0;
if (!SetupDiGetDevicePropertyW(hDevInfo, &DeviceInfoData, &DEVPKEY_Device_BusReportedDeviceDesc,
&devpropType, (BYTE*)productW, 1024, &productSz, 0)) {
if (!SetupDiGetDevicePropertyW(hDevInfo, &DeviceInfoData, &DEVPKEY_Device_BusReportedDeviceDesc, &devpropType,
(BYTE*)productW, 1024, &productSz, 0)) {
/* fallback to SPDRP_DEVICEDESC (USB hubs still use it) */
SetupDiGetDeviceRegistryPropertyA(hDevInfo, &DeviceInfoData, SPDRP_DEVICEDESC,
&reg_type, (BYTE*)productW, 1024, &productSz);
SetupDiGetDeviceRegistryPropertyA(hDevInfo, &DeviceInfoData, SPDRP_DEVICEDESC, &reg_type, (BYTE*)productW, 1024,
&productSz);
}
/* DAFUQ??? Why isn't this really WCHAR??? */
// WideCharToMultiByte(CP_UTF8, 0, productW, -1, product, 1024, nullptr, nullptr);
@ -131,24 +115,18 @@ class HIDListenerWinUSB final : public IHIDListener
WCHAR manufW[1024] = L"Someone"; /* Windows Vista and earlier will use this as the vendor */
CHAR manuf[1024] = {0};
DWORD manufSz = 0;
SetupDiGetDevicePropertyW(hDevInfo, &DeviceInfoData, &DEVPKEY_Device_Manufacturer,
&devpropType, (BYTE*)manufW, 1024, &manufSz, 0);
SetupDiGetDevicePropertyW(hDevInfo, &DeviceInfoData, &DEVPKEY_Device_Manufacturer, &devpropType, (BYTE*)manufW,
1024, &manufSz, 0);
WideCharToMultiByte(CP_UTF8, 0, manufW, -1, manuf, 1024, nullptr, nullptr);
if (type == DeviceType::HID)
{
HANDLE devHnd = CreateFileA(DeviceInterfaceDetailData.wtf.DevicePath,
GENERIC_WRITE | GENERIC_READ,
FILE_SHARE_WRITE | FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
NULL);
if (type == DeviceType::HID) {
HANDLE devHnd = CreateFileA(DeviceInterfaceDetailData.wtf.DevicePath, GENERIC_WRITE | GENERIC_READ,
FILE_SHARE_WRITE | FILE_SHARE_READ, NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);
if (INVALID_HANDLE_VALUE == devHnd)
continue;
PHIDP_PREPARSED_DATA preparsedData;
if (!HidD_GetPreparsedData(devHnd, &preparsedData))
{
if (!HidD_GetPreparsedData(devHnd, &preparsedData)) {
CloseHandle(devHnd);
continue;
}
@ -172,75 +150,59 @@ class HIDListenerWinUSB final : public IHIDListener
continue;
/* Whew!! that's a single device enumerated!! */
m_finder._insertToken(std::make_unique<DeviceToken>(
type, vid, pid, manuf, productW,
DeviceInterfaceDetailData.wtf.DevicePath));
m_finder._insertToken(
std::make_unique<DeviceToken>(type, vid, pid, manuf, productW, DeviceInterfaceDetailData.wtf.DevicePath));
}
SetupDiDestroyDeviceInfoList(hDevInfo);
}
void _pollDevices(const char* pathFilter)
{
void _pollDevices(const char* pathFilter) {
_enumerate(DeviceType::HID, &GUID_DEVINTERFACE_HID, pathFilter);
_enumerate(DeviceType::USB, &GUID_DEVINTERFACE_USB_DEVICE, pathFilter);
}
static XInputPadState ConvertXInputState(const XINPUT_GAMEPAD& pad)
{
return {pad.wButtons, pad.bLeftTrigger, pad.bRightTrigger,
pad.sThumbLX, pad.sThumbLY, pad.sThumbLY, pad.sThumbRY};
static XInputPadState ConvertXInputState(const XINPUT_GAMEPAD& pad) {
return {pad.wButtons, pad.bLeftTrigger, pad.bRightTrigger, pad.sThumbLX, pad.sThumbLY, pad.sThumbLY, pad.sThumbRY};
}
std::thread m_xinputThread;
bool m_xinputRunning = true;
DWORD m_xinputPackets[4] = {DWORD(-1), DWORD(-1), DWORD(-1), DWORD(-1)};
std::vector<DeviceToken> m_xinputTokens;
void _xinputProc()
{
void _xinputProc() {
m_xinputTokens.reserve(4);
for (int i = 0; i < 4; ++i)
m_xinputTokens.emplace_back(DeviceType::XInput, 0, i, "", "", "");
while (m_xinputRunning)
{
for (int i=0 ; i<4 ; ++i)
{
while (m_xinputRunning) {
for (int i = 0; i < 4; ++i) {
DeviceToken& tok = m_xinputTokens[i];
XINPUT_STATE state;
if (XInputGetState(i, &state) == ERROR_SUCCESS)
{
if (state.dwPacketNumber != m_xinputPackets[i])
{
if (XInputGetState(i, &state) == ERROR_SUCCESS) {
if (state.dwPacketNumber != m_xinputPackets[i]) {
if (m_xinputPackets[i] == -1)
m_finder.deviceConnected(tok);
m_xinputPackets[i] = state.dwPacketNumber;
if (tok.m_connectedDev)
{
if (tok.m_connectedDev) {
XInputPad& pad = static_cast<XInputPad&>(*tok.m_connectedDev);
std::lock_guard<std::mutex> lk(pad.m_callbackLock);
if (pad.m_callback)
pad.m_callback->controllerUpdate(pad, ConvertXInputState(state.Gamepad));
}
}
if (tok.m_connectedDev)
{
if (tok.m_connectedDev) {
XInputPad& pad = static_cast<XInputPad&>(*tok.m_connectedDev);
if (pad.m_rumbleRequest[0] != pad.m_rumbleState[0] ||
pad.m_rumbleRequest[1] != pad.m_rumbleState[1])
{
if (pad.m_rumbleRequest[0] != pad.m_rumbleState[0] || pad.m_rumbleRequest[1] != pad.m_rumbleState[1]) {
pad.m_rumbleState[0] = pad.m_rumbleRequest[0];
pad.m_rumbleState[1] = pad.m_rumbleRequest[1];
XINPUT_VIBRATION vibe = {pad.m_rumbleRequest[0], pad.m_rumbleRequest[1]};
XInputSetState(i, &vibe);
}
}
}
else if (m_xinputPackets[i] != -1)
{
} else if (m_xinputPackets[i] != -1) {
m_xinputPackets[i] = -1;
if (tok.m_connectedDev)
{
if (tok.m_connectedDev) {
XInputPad& pad = static_cast<XInputPad&>(*tok.m_connectedDev);
pad.deviceDisconnected();
}
@ -252,51 +214,42 @@ class HIDListenerWinUSB final : public IHIDListener
}
public:
HIDListenerWinUSB(DeviceFinder& finder)
: m_finder(finder)
{
HIDListenerWinUSB(DeviceFinder& finder) : m_finder(finder) {
/* Initial HID Device Add */
_pollDevices(nullptr);
/* XInput arbitration thread */
for (const DeviceSignature* sig : m_finder.getTypes())
{
if (sig->m_type == DeviceType::XInput)
{
for (const DeviceSignature* sig : m_finder.getTypes()) {
if (sig->m_type == DeviceType::XInput) {
m_xinputThread = std::thread(std::bind(&HIDListenerWinUSB::_xinputProc, this));
break;
}
}
}
~HIDListenerWinUSB()
{
~HIDListenerWinUSB() {
m_xinputRunning = false;
if (m_xinputThread.joinable())
m_xinputThread.join();
}
/* Automatic device scanning */
bool startScanning()
{
bool startScanning() {
m_scanningEnabled = true;
return true;
}
bool stopScanning()
{
bool stopScanning() {
m_scanningEnabled = false;
return true;
}
/* Manual device scanning */
bool scanNow()
{
bool scanNow() {
_pollDevices(nullptr);
return true;
}
bool _extDevConnect(const char* path)
{
bool _extDevConnect(const char* path) {
char upperPath[1024];
strcpy_s(upperPath, 1024, path);
CharUpperA(upperPath);
@ -305,8 +258,7 @@ public:
return true;
}
bool _extDevDisconnect(const char* path)
{
bool _extDevDisconnect(const char* path) {
char upperPath[1024];
strcpy_s(upperPath, 1024, path);
CharUpperA(upperPath);
@ -315,9 +267,8 @@ public:
}
};
std::unique_ptr<IHIDListener> IHIDListenerNew(DeviceFinder& finder)
{
std::unique_ptr<IHIDListener> IHIDListenerNew(DeviceFinder& finder) {
return std::make_unique<HIDListenerWinUSB>(finder);
}
}
} // namespace boo

View File

@ -5,34 +5,17 @@
#undef min
#undef max
namespace boo
{
namespace boo {
/* Based on "Device Class Definition for Human Interface Devices (HID)"
* http://www.usb.org/developers/hidpage/HID1_11.pdf
*/
static const char* UsagePageNames[] =
{
"Undefined",
"Generic Desktop",
"Simulation",
"VR",
"Sport",
"Game Controls",
"Generic Device",
"Keyboard",
"LEDs",
"Button",
"Ordinal",
"Telephony",
"Consumer",
"Digitizer"
};
static const char* UsagePageNames[] = {"Undefined", "Generic Desktop", "Simulation", "VR", "Sport",
"Game Controls", "Generic Device", "Keyboard", "LEDs", "Button",
"Ordinal", "Telephony", "Consumer", "Digitizer"};
static const char* GenericDesktopUsages[] =
{
"Undefined",
static const char* GenericDesktopUsages[] = {"Undefined",
"Pointer",
"Mouse",
"Reserved",
@ -42,13 +25,44 @@ static const char* GenericDesktopUsages[] =
"Keypad",
"Multi-axis Controller",
"Tablet PC System Controls",
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
nullptr, nullptr, nullptr, nullptr, nullptr,
nullptr, nullptr, nullptr, nullptr, nullptr,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
nullptr, nullptr, nullptr, nullptr, nullptr,
nullptr, nullptr, nullptr, nullptr, nullptr,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
"X",
"Y",
"Z",
@ -74,16 +88,61 @@ static const char* GenericDesktopUsages[] =
"Vno",
"Feature Notification",
"Resolution Multiplier",
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
nullptr, nullptr, nullptr, nullptr, nullptr,
nullptr, nullptr, nullptr, nullptr, nullptr,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
nullptr, nullptr, nullptr, nullptr, nullptr,
nullptr, nullptr, nullptr, nullptr, nullptr,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
nullptr, nullptr, nullptr, nullptr, nullptr,
nullptr, nullptr, nullptr, nullptr, nullptr,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
"System Control",
"System Power Down",
"System Sleep",
@ -104,8 +163,18 @@ static const char* GenericDesktopUsages[] =
"D-pad Down",
"D-pad Right",
"D-pad Left",
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
"System Dock",
"System Undock",
"System Setup",
@ -115,26 +184,52 @@ static const char* GenericDesktopUsages[] =
"Application Debugger Break",
"System Speaker Mute",
"System Hibernate",
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
"System Display Invert",
"System Display Internal",
"System Display External",
"System Display Both",
"System Display Dual",
"System Display Toggle Int/Ext"
};
"System Display Toggle Int/Ext"};
static const char* GameUsages[] =
{
"Undefined",
static const char* GameUsages[] = {"Undefined",
"3D Game Controller",
"Pinball Device",
"Gun Device",
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
nullptr, nullptr, nullptr, nullptr, nullptr,
nullptr, nullptr, nullptr, nullptr, nullptr,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
"Point of View",
"Turn Right/Left",
"Pitch Forward/Backward",
@ -160,11 +255,9 @@ static const char* GameUsages[] =
"Gun Safety",
"Gemepad Fire/Jump",
nullptr,
"Gamepad Trigger"
};
"Gamepad Trigger"};
enum class HIDCollectionType : uint8_t
{
enum class HIDCollectionType : uint8_t {
Physical,
Application,
Logical,
@ -174,16 +267,9 @@ enum class HIDCollectionType : uint8_t
UsageModifier
};
enum class HIDItemType : uint8_t
{
Main,
Global,
Local,
Reserved
};
enum class HIDItemType : uint8_t { Main, Global, Local, Reserved };
enum class HIDItemTag : uint8_t
{
enum class HIDItemTag : uint8_t {
/* [6.2.2.4] Main Items */
Input = 0b1000,
Output = 0b1001,
@ -218,8 +304,7 @@ enum class HIDItemTag : uint8_t
Delimiter = 0b1010,
};
struct HIDItemState
{
struct HIDItemState {
/* [6.2.2.7] Global items */
HIDUsagePage m_usagePage = HIDUsagePage::Undefined;
HIDRange m_logicalRange = {};
@ -241,8 +326,7 @@ struct HIDItemState
std::vector<int32_t> m_delimiter;
#endif
void ResetLocalItems()
{
void ResetLocalItems() {
m_usage.clear();
m_usageRange = HIDRange();
#if 0
@ -255,8 +339,7 @@ struct HIDItemState
}
template <typename T>
static T _GetLocal(const std::vector<T>& v, uint32_t idx)
{
static T _GetLocal(const std::vector<T>& v, uint32_t idx) {
if (v.empty())
return {};
if (idx >= v.size())
@ -264,52 +347,46 @@ struct HIDItemState
return v[idx];
}
HIDUsage GetUsage(uint32_t idx) const
{
HIDUsage GetUsage(uint32_t idx) const {
if (m_usageRange.second - m_usageRange.first != 0)
return HIDUsage(m_usageRange.first + idx);
return _GetLocal(m_usage, idx);
}
};
struct HIDCollectionItem
{
struct HIDCollectionItem {
/* [6.2.2.6] Collection, End Collection Items */
HIDCollectionType m_type;
HIDUsagePage m_usagePage;
HIDUsage m_usage;
HIDCollectionItem(HIDCollectionType type, const HIDItemState& state)
: m_type(type), m_usagePage(state.m_usagePage), m_usage(state.GetUsage(0))
{}
: m_type(type), m_usagePage(state.m_usagePage), m_usage(state.GetUsage(0)) {}
};
HIDMainItem::HIDMainItem(uint32_t flags, const HIDItemState& state, uint32_t reportIdx)
: m_flags(uint16_t(flags))
{
HIDMainItem::HIDMainItem(uint32_t flags, const HIDItemState& state, uint32_t reportIdx) : m_flags(uint16_t(flags)) {
m_usagePage = state.m_usagePage;
m_usage = state.GetUsage(reportIdx);
m_logicalRange = state.m_logicalRange;
m_reportSize = state.m_reportSize;
}
HIDMainItem::HIDMainItem(uint32_t flags, HIDUsagePage usagePage, HIDUsage usage,
HIDRange logicalRange, int32_t reportSize)
: m_flags(uint16_t(flags)), m_usagePage(usagePage), m_usage(usage),
m_logicalRange(logicalRange), m_reportSize(reportSize)
{}
HIDMainItem::HIDMainItem(uint32_t flags, HIDUsagePage usagePage, HIDUsage usage, HIDRange logicalRange,
int32_t reportSize)
: m_flags(uint16_t(flags))
, m_usagePage(usagePage)
, m_usage(usage)
, m_logicalRange(logicalRange)
, m_reportSize(reportSize) {}
const char* HIDMainItem::GetUsagePageName() const
{
const char* HIDMainItem::GetUsagePageName() const {
if (int(m_usagePage) >= std::extent<decltype(UsagePageNames)>::value)
return nullptr;
return UsagePageNames[int(m_usagePage)];
}
const char* HIDMainItem::GetUsageName() const
{
switch (m_usagePage)
{
const char* HIDMainItem::GetUsageName() const {
switch (m_usagePage) {
case HIDUsagePage::GenericDesktop:
if (int(m_usage) >= std::extent<decltype(GenericDesktopUsages)>::value)
return nullptr;
@ -323,14 +400,12 @@ const char* HIDMainItem::GetUsageName() const
}
}
struct HIDReports
{
struct HIDReports {
std::map<int32_t, std::vector<HIDMainItem>> m_inputReports;
std::map<int32_t, std::vector<HIDMainItem>> m_outputReports;
std::map<int32_t, std::vector<HIDMainItem>> m_featureReports;
static void _AddItem(std::map<int32_t, std::vector<HIDMainItem>>& m, uint32_t flags, const HIDItemState& state)
{
static void _AddItem(std::map<int32_t, std::vector<HIDMainItem>>& m, uint32_t flags, const HIDItemState& state) {
std::vector<HIDMainItem>& report = m[state.m_reportID];
report.reserve(report.size() + state.m_reportCount);
for (int i = 0; i < state.m_reportCount; ++i)
@ -344,8 +419,7 @@ struct HIDReports
#if _WIN32
#if !WINDOWS_STORE
HIDParser::ParserStatus HIDParser::Parse(const PHIDP_PREPARSED_DATA descriptorData)
{
HIDParser::ParserStatus HIDParser::Parse(const PHIDP_PREPARSED_DATA descriptorData) {
/* User mode HID report descriptor isn't available on Win32.
* Opaque preparsed data must be enumerated and sorted into
* iterable items.
@ -369,20 +443,14 @@ HIDParser::ParserStatus HIDParser::Parse(const PHIDP_PREPARSED_DATA descriptorDa
USHORT length = caps.NumberInputButtonCaps;
std::vector<HIDP_BUTTON_CAPS> bCaps(caps.NumberInputButtonCaps, HIDP_BUTTON_CAPS());
HidP_GetButtonCaps(HidP_Input, bCaps.data(), &length, descriptorData);
for (const HIDP_BUTTON_CAPS& caps : bCaps)
{
if (caps.IsRange)
{
for (const HIDP_BUTTON_CAPS& caps : bCaps) {
if (caps.IsRange) {
int usage = caps.Range.UsageMin;
for (int i=caps.Range.DataIndexMin ; i<=caps.Range.DataIndexMax ; ++i, ++usage)
{
inputItems.insert(std::make_pair(i,
HIDMainItem(caps.BitField, HIDUsagePage(caps.UsagePage),
HIDUsage(usage), std::make_pair(0, 1), 1)));
for (int i = caps.Range.DataIndexMin; i <= caps.Range.DataIndexMax; ++i, ++usage) {
inputItems.insert(std::make_pair(
i, HIDMainItem(caps.BitField, HIDUsagePage(caps.UsagePage), HIDUsage(usage), std::make_pair(0, 1), 1)));
}
}
else
{
} else {
inputItems.insert(std::make_pair(caps.NotRange.DataIndex,
HIDMainItem(caps.BitField, HIDUsagePage(caps.UsagePage),
HIDUsage(caps.NotRange.Usage), std::make_pair(0, 1), 1)));
@ -395,21 +463,17 @@ HIDParser::ParserStatus HIDParser::Parse(const PHIDP_PREPARSED_DATA descriptorDa
USHORT length = caps.NumberInputValueCaps;
std::vector<HIDP_VALUE_CAPS> vCaps(caps.NumberInputValueCaps, HIDP_VALUE_CAPS());
HidP_GetValueCaps(HidP_Input, vCaps.data(), &length, descriptorData);
for (const HIDP_VALUE_CAPS& caps : vCaps)
{
if (caps.IsRange)
{
for (const HIDP_VALUE_CAPS& caps : vCaps) {
if (caps.IsRange) {
int usage = caps.Range.UsageMin;
for (int i=caps.Range.DataIndexMin ; i<=caps.Range.DataIndexMax ; ++i, ++usage)
{
inputItems.insert(std::make_pair(i,
HIDMainItem(caps.BitField, HIDUsagePage(caps.UsagePage), HIDUsage(usage),
for (int i = caps.Range.DataIndexMin; i <= caps.Range.DataIndexMax; ++i, ++usage) {
inputItems.insert(
std::make_pair(i, HIDMainItem(caps.BitField, HIDUsagePage(caps.UsagePage), HIDUsage(usage),
std::make_pair(caps.LogicalMin, caps.LogicalMax), caps.BitSize)));
}
}
else
{
inputItems.insert(std::make_pair(caps.NotRange.DataIndex,
} else {
inputItems.insert(
std::make_pair(caps.NotRange.DataIndex,
HIDMainItem(caps.BitField, HIDUsagePage(caps.UsagePage), HIDUsage(caps.NotRange.Usage),
HIDRange(caps.LogicalMin, caps.LogicalMax), caps.BitSize)));
}
@ -426,25 +490,18 @@ HIDParser::ParserStatus HIDParser::Parse(const PHIDP_PREPARSED_DATA descriptorDa
#endif
#else
static HIDParser::ParserStatus
AdvanceIt(const uint8_t*& it, const uint8_t* end, size_t adv)
{
static HIDParser::ParserStatus AdvanceIt(const uint8_t*& it, const uint8_t* end, size_t adv) {
it += adv;
if (it > end)
{
if (it > end) {
it = end;
return HIDParser::ParserStatus::Error;
}
else if (it == end)
{
} else if (it == end) {
return HIDParser::ParserStatus::Done;
}
return HIDParser::ParserStatus::OK;
}
static uint8_t
GetByteValue(const uint8_t*& it, const uint8_t* end, HIDParser::ParserStatus& status)
{
static uint8_t GetByteValue(const uint8_t*& it, const uint8_t* end, HIDParser::ParserStatus& status) {
const uint8_t* oldIt = it;
status = AdvanceIt(it, end, 1);
if (status == HIDParser::ParserStatus::Error)
@ -452,12 +509,9 @@ GetByteValue(const uint8_t*& it, const uint8_t* end, HIDParser::ParserStatus& st
return *oldIt;
}
static uint32_t
GetShortValue(const uint8_t*& it, const uint8_t* end, int adv, HIDParser::ParserStatus& status)
{
static uint32_t GetShortValue(const uint8_t*& it, const uint8_t* end, int adv, HIDParser::ParserStatus& status) {
const uint8_t* oldIt = it;
switch (adv)
{
switch (adv) {
case 1:
status = AdvanceIt(it, end, 1);
if (status == HIDParser::ParserStatus::Error)
@ -479,17 +533,12 @@ GetShortValue(const uint8_t*& it, const uint8_t* end, int adv, HIDParser::Parser
return 0;
}
HIDParser::ParserStatus
HIDParser::ParseItem(HIDReports& reportsOut,
std::stack<HIDItemState>& stateStack,
std::stack<HIDCollectionItem>& collectionStack,
const uint8_t*& it, const uint8_t* end,
bool& multipleReports)
{
HIDParser::ParserStatus HIDParser::ParseItem(HIDReports& reportsOut, std::stack<HIDItemState>& stateStack,
std::stack<HIDCollectionItem>& collectionStack, const uint8_t*& it,
const uint8_t* end, bool& multipleReports) {
ParserStatus status = ParserStatus::OK;
uint8_t head = *it++;
if (head == 0b11111110)
{
if (head == 0b11111110) {
/* Long item */
uint8_t bDataSize = GetByteValue(it, end, status);
if (status == ParserStatus::Error)
@ -500,19 +549,15 @@ HIDParser::ParseItem(HIDReports& reportsOut,
status = AdvanceIt(it, end, bDataSize);
if (status == ParserStatus::Error)
return ParserStatus::Error;
}
else
{
} else {
/* Short Item */
uint32_t data = GetShortValue(it, end, head & 0x3, status);
if (status == ParserStatus::Error)
return ParserStatus::Error;
switch (HIDItemType((head >> 2) & 0x3))
{
switch (HIDItemType((head >> 2) & 0x3)) {
case HIDItemType::Main:
switch (HIDItemTag(head >> 4))
{
switch (HIDItemTag(head >> 4)) {
case HIDItemTag::Input:
reportsOut.AddInputItem(data, stateStack.top());
break;
@ -536,8 +581,7 @@ HIDParser::ParseItem(HIDReports& reportsOut,
stateStack.top().ResetLocalItems();
break;
case HIDItemType::Global:
switch (HIDItemTag(head >> 4))
{
switch (HIDItemTag(head >> 4)) {
case HIDItemTag::UsagePage:
stateStack.top().m_usagePage = HIDUsagePage(data);
break;
@ -582,8 +626,7 @@ HIDParser::ParseItem(HIDReports& reportsOut,
}
break;
case HIDItemType::Local:
switch (HIDItemTag(head >> 4))
{
switch (HIDItemTag(head >> 4)) {
case HIDItemTag::Usage:
stateStack.top().m_usage.push_back(HIDUsage(data));
break;
@ -608,14 +651,12 @@ HIDParser::ParseItem(HIDReports& reportsOut,
default:
return ParserStatus::Error;
}
}
return it == end ? ParserStatus::Done : ParserStatus::OK;
}
HIDParser::ParserStatus HIDParser::Parse(const uint8_t* descriptorData, size_t len)
{
HIDParser::ParserStatus HIDParser::Parse(const uint8_t* descriptorData, size_t len) {
std::stack<HIDItemState> stateStack;
stateStack.emplace();
std::stack<HIDCollectionItem> collectionStack;
@ -623,16 +664,15 @@ HIDParser::ParserStatus HIDParser::Parse(const uint8_t* descriptorData, size_t l
const uint8_t* end = descriptorData + len;
for (const uint8_t* it = descriptorData; it != end;)
if ((m_status =
ParseItem(reports, stateStack, collectionStack, it, end, m_multipleReports)) != ParserStatus::OK)
if ((m_status = ParseItem(reports, stateStack, collectionStack, it, end, m_multipleReports)) != ParserStatus::OK)
break;
if (m_status != ParserStatus::Done)
return m_status;
uint32_t itemCount = 0;
uint32_t reportCount = uint32_t(reports.m_inputReports.size() + reports.m_outputReports.size() +
reports.m_featureReports.size());
uint32_t reportCount =
uint32_t(reports.m_inputReports.size() + reports.m_outputReports.size() + reports.m_featureReports.size());
for (const auto& rep : reports.m_inputReports)
itemCount += rep.second.size();
@ -647,13 +687,10 @@ HIDParser::ParserStatus HIDParser::Parse(const uint8_t* descriptorData, size_t l
uint32_t itemIndex = 0;
uint32_t reportIndex = 0;
auto func = [&](std::pair<uint32_t, uint32_t>& out, const std::map<int32_t, std::vector<HIDMainItem>>& in)
{
auto func = [&](std::pair<uint32_t, uint32_t>& out, const std::map<int32_t, std::vector<HIDMainItem>>& in) {
out = std::make_pair(reportIndex, reportIndex + in.size());
for (const auto& rep : in)
{
m_reportPool[reportIndex++] =
std::make_pair(rep.first, std::make_pair(itemIndex, itemIndex + rep.second.size()));
for (const auto& rep : in) {
m_reportPool[reportIndex++] = std::make_pair(rep.first, std::make_pair(itemIndex, itemIndex + rep.second.size()));
for (const auto& item : rep.second)
m_itemPool[itemIndex++] = item;
}
@ -665,8 +702,7 @@ HIDParser::ParserStatus HIDParser::Parse(const uint8_t* descriptorData, size_t l
return m_status;
}
size_t HIDParser::CalculateMaxInputReportSize(const uint8_t* descriptorData, size_t len)
{
size_t HIDParser::CalculateMaxInputReportSize(const uint8_t* descriptorData, size_t len) {
std::stack<HIDItemState> stateStack;
stateStack.emplace();
std::stack<HIDCollectionItem> collectionStack;
@ -683,8 +719,7 @@ size_t HIDParser::CalculateMaxInputReportSize(const uint8_t* descriptorData, siz
return 0;
size_t maxSize = 0;
for (const auto& rep : reports.m_inputReports)
{
for (const auto& rep : reports.m_inputReports) {
size_t repSize = 0;
for (const auto& item : rep.second)
repSize += item.m_reportSize;
@ -695,8 +730,7 @@ size_t HIDParser::CalculateMaxInputReportSize(const uint8_t* descriptorData, siz
return (maxSize + 7) / 8 + multipleReports;
}
std::pair<HIDUsagePage, HIDUsage> HIDParser::GetApplicationUsage(const uint8_t* descriptorData, size_t len)
{
std::pair<HIDUsagePage, HIDUsage> HIDParser::GetApplicationUsage(const uint8_t* descriptorData, size_t len) {
std::stack<HIDItemState> stateStack;
stateStack.emplace();
std::stack<HIDCollectionItem> collectionStack;
@ -705,8 +739,7 @@ std::pair<HIDUsagePage, HIDUsage> HIDParser::GetApplicationUsage(const uint8_t*
bool multipleReports = false;
const uint8_t* end = descriptorData + len;
for (const uint8_t* it = descriptorData; it != end;)
{
for (const uint8_t* it = descriptorData; it != end;) {
status = ParseItem(reports, stateStack, collectionStack, it, end, multipleReports);
if (collectionStack.empty())
continue;
@ -721,14 +754,12 @@ std::pair<HIDUsagePage, HIDUsage> HIDParser::GetApplicationUsage(const uint8_t*
#endif
#if _WIN32
void HIDParser::EnumerateValues(const std::function<bool(const HIDMainItem& item)>& valueCB) const
{
void HIDParser::EnumerateValues(const std::function<bool(const HIDMainItem& item)>& valueCB) const {
#if !WINDOWS_STORE
if (m_status != ParserStatus::Done)
return;
for (const HIDMainItem& item : m_itemPool)
{
for (const HIDMainItem& item : m_itemPool) {
if (item.IsConstant())
continue;
if (!valueCB(item))
@ -737,16 +768,13 @@ void HIDParser::EnumerateValues(const std::function<bool(const HIDMainItem& item
#endif
}
#else
void HIDParser::EnumerateValues(const std::function<bool(const HIDMainItem& item)>& valueCB) const
{
void HIDParser::EnumerateValues(const std::function<bool(const HIDMainItem& item)>& valueCB) const {
if (m_status != ParserStatus::Done)
return;
for (uint32_t i=m_inputReports.first ; i<m_inputReports.second ; ++i)
{
for (uint32_t i = m_inputReports.first; i < m_inputReports.second; ++i) {
const Report& rep = m_reportPool[i];
for (uint32_t j=rep.second.first ; j<rep.second.second ; ++j)
{
for (uint32_t j = rep.second.first; j < rep.second.second; ++j) {
const HIDMainItem& item = m_itemPool[j];
if (item.IsConstant())
continue;
@ -759,30 +787,25 @@ void HIDParser::EnumerateValues(const std::function<bool(const HIDMainItem& item
#if _WIN32
void HIDParser::ScanValues(const std::function<bool(const HIDMainItem& item, int32_t value)>& valueCB,
const uint8_t* data, size_t len) const
{
const uint8_t* data, size_t len) const {
#if !WINDOWS_STORE
if (m_status != ParserStatus::Done)
return;
ULONG dataLen = m_dataList.size();
if (HidP_GetData(HidP_Input, m_dataList.data(), &dataLen,
m_descriptorData, PCHAR(data), len) != HIDP_STATUS_SUCCESS)
if (HidP_GetData(HidP_Input, m_dataList.data(), &dataLen, m_descriptorData, PCHAR(data), len) != HIDP_STATUS_SUCCESS)
return;
int idx = 0;
auto it = m_dataList.begin();
auto end = m_dataList.begin() + dataLen;
for (const HIDMainItem& item : m_itemPool)
{
for (const HIDMainItem& item : m_itemPool) {
if (item.IsConstant())
continue;
int32_t value = 0;
if (it != end)
{
if (it != end) {
const HIDP_DATA& data = *it;
if (data.DataIndex == idx)
{
if (data.DataIndex == idx) {
value = data.RawValue;
++it;
}
@ -795,22 +818,18 @@ void HIDParser::ScanValues(const std::function<bool(const HIDMainItem& item, int
}
#else
class BitwiseIterator
{
class BitwiseIterator {
const uint8_t*& m_it;
const uint8_t* m_end;
int m_bit = 0;
public:
BitwiseIterator(const uint8_t*& it, const uint8_t* end)
: m_it(it), m_end(end) {}
uint32_t GetUnsignedValue(int numBits, HIDParser::ParserStatus& status)
{
public:
BitwiseIterator(const uint8_t*& it, const uint8_t* end) : m_it(it), m_end(end) {}
uint32_t GetUnsignedValue(int numBits, HIDParser::ParserStatus& status) {
uint32_t val = 0;
for (int i=0 ; i<numBits ;)
{
if (m_it >= m_end)
{
for (int i = 0; i < numBits;) {
if (m_it >= m_end) {
status = HIDParser::ParserStatus::Error;
return 0;
}
@ -818,8 +837,7 @@ public:
val |= uint32_t((*m_it >> m_bit) & ((1 << remBits) - 1)) << i;
i += remBits;
m_bit += remBits;
if (m_bit == 8)
{
if (m_bit == 8) {
m_bit = 0;
AdvanceIt(m_it, m_end, 1);
}
@ -829,8 +847,7 @@ public:
};
void HIDParser::ScanValues(const std::function<bool(const HIDMainItem& item, int32_t value)>& valueCB,
const uint8_t* data, size_t len) const
{
const uint8_t* data, size_t len) const {
if (m_status != ParserStatus::Done)
return;
@ -845,13 +862,11 @@ void HIDParser::ScanValues(const std::function<bool(const HIDMainItem& item, int
BitwiseIterator bitIt(it, end);
for (uint32_t i=m_inputReports.first ; i<m_inputReports.second ; ++i)
{
for (uint32_t i = m_inputReports.first; i < m_inputReports.second; ++i) {
const Report& rep = m_reportPool[i];
if (rep.first != reportId)
continue;
for (uint32_t j=rep.second.first ; j<rep.second.second ; ++j)
{
for (uint32_t j = rep.second.first; j < rep.second.second; ++j) {
const HIDMainItem& item = m_itemPool[j];
int32_t val = bitIt.GetUnsignedValue(item.m_reportSize, status);
if (status == ParserStatus::Error)
@ -866,4 +881,4 @@ void HIDParser::ScanValues(const std::function<bool(const HIDMainItem& item, int
}
#endif
}
} // namespace boo

View File

@ -8,11 +8,9 @@
#include <hidsdi.h>
#endif
namespace boo
{
namespace boo {
class IHIDDevice : public std::enable_shared_from_this<IHIDDevice>
{
class IHIDDevice : public std::enable_shared_from_this<IHIDDevice> {
friend class DeviceBase;
friend struct DeviceSignature;
virtual void _deviceDisconnected() = 0;
@ -28,9 +26,9 @@ class IHIDDevice : public std::enable_shared_from_this<IHIDDevice>
virtual bool _sendHIDReport(const uint8_t* data, size_t length, HIDReportType tp, uint32_t message) = 0;
virtual size_t _receiveHIDReport(uint8_t* data, size_t length, HIDReportType tp, uint32_t message) = 0;
virtual void _startThread() = 0;
public:
virtual ~IHIDDevice() = default;
};
}
} // namespace boo

View File

@ -42,15 +42,10 @@ public:
}
}
static inline IOObjectPointer<T> adopt(T ptr) {
return IOObjectPointer<T>(ptr, IOObjectPointer<T>::Adopt);
}
static inline IOObjectPointer<T> adopt(T ptr) { return IOObjectPointer<T>(ptr, IOObjectPointer<T>::Adopt); }
T get() const {
return fromStorageType(storage);
}
io_object_t* operator&()
{
T get() const { return fromStorageType(storage); }
io_object_t* operator&() {
if (io_object_t pointer = storage) {
IOObjectRelease(pointer);
}
@ -64,17 +59,11 @@ private:
enum AdoptTag { Adopt };
IOObjectPointer(T ptr, AdoptTag) : storage(toStorageType(ptr)) {}
inline io_object_t toStorageType(io_object_t ptr) const {
return (io_object_t)ptr;
}
inline io_object_t toStorageType(io_object_t ptr) const { return (io_object_t)ptr; }
inline T fromStorageType(io_object_t pointer) const {
return (T)pointer;
}
inline T fromStorageType(io_object_t pointer) const { return (T)pointer; }
void swap(IOObjectPointer &other) {
std::swap(storage, other.storage);
}
void swap(IOObjectPointer& other) { std::swap(storage, other.storage); }
};
/// A smart pointer that can manage the lifecycle of IOKit plugin objects.
@ -92,16 +81,14 @@ public:
}
}
IOCFPlugInInterface*** operator&()
{
IOCFPlugInInterface*** operator&() {
if (IOCFPlugInInterface** pointer = _storage) {
IODestroyPlugInInterface(pointer);
}
return &_storage;
}
HRESULT As(LPVOID* p, CFUUIDRef uuid) const
{
HRESULT As(LPVOID* p, CFUUIDRef uuid) const {
(*_storage)->AddRef(_storage); // Needed for some reason
return (*_storage)->QueryInterface(_storage, CFUUIDGetUUIDBytes(uuid), p);
}
@ -112,8 +99,5 @@ public:
private:
IOCFPlugInInterface** _storage;
void swap(IOCFPluginPointer &other) {
std::swap(_storage, other._storage);
}
void swap(IOCFPluginPointer& other) { std::swap(_storage, other._storage); }
};

View File

@ -1,20 +1,13 @@
#include "boo/inputdev/NintendoPowerA.hpp"
#include "boo/inputdev/DeviceSignature.hpp"
#include <memory.h>
namespace boo
{
namespace boo {
NintendoPowerA::NintendoPowerA(DeviceToken* token)
: TDeviceBase<INintendoPowerACallback>(dev_typeid(NintendoPowerA), token)
{
: TDeviceBase<INintendoPowerACallback>(dev_typeid(NintendoPowerA), token) {}
}
NintendoPowerA::~NintendoPowerA() {}
NintendoPowerA::~NintendoPowerA()
{
}
void NintendoPowerA::deviceDisconnected()
{
void NintendoPowerA::deviceDisconnected() {
std::lock_guard<std::mutex> lk(m_callbackLock);
if (m_callback)
m_callback->controllerDisconnected();
@ -22,8 +15,7 @@ void NintendoPowerA::deviceDisconnected()
void NintendoPowerA::initialCycle() {}
void NintendoPowerA::transferCycle()
{
void NintendoPowerA::transferCycle() {
uint8_t payload[8];
size_t recvSz = receiveUSBInterruptTransfer(payload, sizeof(payload));
if (recvSz != 8)
@ -39,18 +31,14 @@ void NintendoPowerA::transferCycle()
void NintendoPowerA::finalCycle() {}
void NintendoPowerA::receivedHIDReport(const uint8_t* data, size_t length, HIDReportType tp, uint32_t message)
{
}
void NintendoPowerA::receivedHIDReport(const uint8_t* data, size_t length, HIDReportType tp, uint32_t message) {}
bool NintendoPowerAState::operator==(const NintendoPowerAState &other)
{
bool NintendoPowerAState::operator==(const NintendoPowerAState& other) {
return !memcmp(this, &other, sizeof(NintendoPowerAState));
}
bool NintendoPowerAState::operator!=(const NintendoPowerAState &other)
{
bool NintendoPowerAState::operator!=(const NintendoPowerAState& other) {
return memcmp(this, &other, sizeof(NintendoPowerAState));
}
}
} // namespace boo

View File

@ -12,15 +12,12 @@
#include <unordered_map>
#include <mutex>
namespace boo
{
namespace boo {
class IWindow;
struct MetalContext
{
struct MetalContext {
id<MTLDevice> m_dev = nullptr;
id<MTLCommandQueue> m_q = nullptr;
struct Window
{
struct Window {
CAMetalLayer* m_metalLayer = nullptr;
std::mutex m_resizeLock;
bool m_needsResize;
@ -31,13 +28,12 @@ struct MetalContext
uint32_t m_anisotropy = 1;
MTLPixelFormat m_pixelFormat = MTLPixelFormatBGRA8Unorm;
};
}
} // namespace boo
#else
namespace boo
{
namespace boo {
struct MetalContext {};
}
} // namespace boo
#endif
#endif // __APPLE__

View File

@ -7,14 +7,12 @@
#include <switch.h>
namespace boo
{
namespace boo {
static logvisor::Module Log("boo::NXApplication");
std::shared_ptr<IWindow> _WindowNXNew(std::string_view title, NXContext* nxCtx);
class ApplicationNX : public IApplication
{
class ApplicationNX : public IApplication {
IApplicationCallback& m_callback;
const std::string m_uniqueName;
const std::string m_friendlyName;
@ -26,34 +24,20 @@ class ApplicationNX : public IApplication
void _deletedWindow(IWindow* window) {}
public:
ApplicationNX(IApplicationCallback& callback,
std::string_view uniqueName,
std::string_view friendlyName,
std::string_view pname,
const std::vector<std::string>& args,
std::string_view gfxApi,
uint32_t samples,
uint32_t anisotropy,
bool deepColor,
bool singleInstance)
: m_callback(callback),
m_uniqueName(uniqueName),
m_friendlyName(friendlyName),
m_pname(pname),
m_args(args)
{}
ApplicationNX(IApplicationCallback& callback, std::string_view uniqueName, std::string_view friendlyName,
std::string_view pname, const std::vector<std::string>& args, std::string_view gfxApi, uint32_t samples,
uint32_t anisotropy, bool deepColor, bool singleInstance)
: m_callback(callback), m_uniqueName(uniqueName), m_friendlyName(friendlyName), m_pname(pname), m_args(args) {}
EPlatformType getPlatformType() const { return EPlatformType::NX; }
int run()
{
int run() {
/* Spawn client thread */
int clientReturn = INT_MIN;
std::mutex initmt;
std::condition_variable initcv;
std::unique_lock<std::mutex> outerLk(initmt);
std::thread clientThread([&]()
{
std::thread clientThread([&]() {
std::unique_lock<std::mutex> innerLk(initmt);
innerLk.unlock();
initcv.notify_one();
@ -64,8 +48,7 @@ public:
initcv.wait(outerLk);
// Main graphics loop
while (clientReturn == INT_MIN && appletMainLoop())
{
while (clientReturn == INT_MIN && appletMainLoop()) {
// Get and process input
hidScanInput();
u32 kDown = hidKeysDown(CONTROLLER_P1_AUTO);
@ -80,29 +63,16 @@ public:
return 0;
}
std::string_view getUniqueName() const
{
return m_uniqueName;
}
std::string_view getUniqueName() const { return m_uniqueName; }
std::string_view getFriendlyName() const
{
return m_friendlyName;
}
std::string_view getFriendlyName() const { return m_friendlyName; }
std::string_view getProcessName() const
{
return m_pname;
}
std::string_view getProcessName() const { return m_pname; }
const std::vector<std::string>& getArgs() const
{
return m_args;
}
const std::vector<std::string>& getArgs() const { return m_args; }
std::shared_ptr<IWindow> m_window;
std::shared_ptr<IWindow> newWindow(std::string_view title)
{
std::shared_ptr<IWindow> newWindow(std::string_view title) {
if (m_window)
Log.report(logvisor::Fatal, "Only 1 window allowed on NX");
m_window = _WindowNXNew(title, &m_nxCtx);
@ -111,29 +81,21 @@ public:
};
IApplication* APP = nullptr;
int ApplicationRun(IApplication::EPlatformType platform,
IApplicationCallback& cb,
SystemStringView uniqueName,
SystemStringView friendlyName,
SystemStringView pname,
const std::vector<SystemString>& args,
std::string_view gfxApi,
uint32_t samples,
uint32_t anisotropy,
bool deepColor,
bool singleInstance)
{
int ApplicationRun(IApplication::EPlatformType platform, IApplicationCallback& cb, SystemStringView uniqueName,
SystemStringView friendlyName, SystemStringView pname, const std::vector<SystemString>& args,
std::string_view gfxApi, uint32_t samples, uint32_t anisotropy, bool deepColor,
bool singleInstance) {
std::string thrName = std::string(friendlyName) + " Main Thread";
logvisor::RegisterThreadName(thrName.c_str());
if (APP)
return 1;
APP = new ApplicationNX(cb, uniqueName, friendlyName, pname, args, gfxApi,
samples, anisotropy, deepColor, singleInstance);
APP = new ApplicationNX(cb, uniqueName, friendlyName, pname, args, gfxApi, samples, anisotropy, deepColor,
singleInstance);
int ret = APP->run();
delete APP;
APP = nullptr;
return ret;
}
}
} // namespace boo

View File

@ -5,21 +5,18 @@
#include <switch.h>
namespace boo
{
namespace boo {
std::unique_ptr<IGraphicsCommandQueue> _NewNXCommandQueue(NXContext* ctx, IGraphicsContext* parent);
std::unique_ptr<IGraphicsDataFactory> _NewNXDataFactory(IGraphicsContext* parent, NXContext* ctx);
struct GraphicsContextNX : IGraphicsContext
{
struct GraphicsContextNX : IGraphicsContext {
NXContext* m_nxCtx;
std::unique_ptr<IGraphicsDataFactory> m_dataFactory;
std::unique_ptr<IGraphicsCommandQueue> m_commandQueue;
public:
explicit GraphicsContextNX(NXContext* nxCtx)
: m_nxCtx(nxCtx)
{
explicit GraphicsContextNX(NXContext* nxCtx) : m_nxCtx(nxCtx) {
m_dataFactory = _NewNXDataFactory(this, nxCtx);
m_commandQueue = _NewNXCommandQueue(nxCtx, this);
}
@ -38,15 +35,13 @@ public:
IGraphicsDataFactory* getLoadContextDataFactory() { return m_dataFactory.get(); }
};
class WindowNX : public IWindow
{
class WindowNX : public IWindow {
std::string m_title;
std::unique_ptr<GraphicsContextNX> m_gfxCtx;
IWindowCallback* m_callback = nullptr;
public:
WindowNX(std::string_view title, NXContext* nxCtx)
: m_title(title), m_gfxCtx(new GraphicsContextNX(nxCtx))
{
WindowNX(std::string_view title, NXContext* nxCtx) : m_title(title), m_gfxCtx(new GraphicsContextNX(nxCtx)) {
m_gfxCtx->initializeContext(nullptr);
}
@ -63,8 +58,7 @@ public:
void setWaitCursor(bool wait) {}
void setWindowFrameDefault() {}
void getWindowFrame(float& xOut, float& yOut, float& wOut, float& hOut) const
{
void getWindowFrame(float& xOut, float& yOut, float& wOut, float& hOut) const {
u32 width, height;
gfxGetFramebufferResolution(&width, &height);
xOut = 0;
@ -72,8 +66,7 @@ public:
wOut = width;
hOut = height;
}
void getWindowFrame(int& xOut, int& yOut, int& wOut, int& hOut) const
{
void getWindowFrame(int& xOut, int& yOut, int& wOut, int& hOut) const {
u32 width, height;
gfxGetFramebufferResolution(&width, &height);
xOut = 0;
@ -95,7 +88,10 @@ public:
void waitForRetrace() {}
uintptr_t getPlatformHandle() const { return 0; }
bool _incomingEvent(void* event) {(void)event; return false;}
bool _incomingEvent(void* event) {
(void)event;
return false;
}
void _cleanup() {}
ETouchType getTouchType() const { return ETouchType::Display; }
@ -111,10 +107,9 @@ public:
IGraphicsDataFactory* getLoadContextDataFactory() { return m_gfxCtx->getLoadContextDataFactory(); }
};
std::shared_ptr<IWindow> _WindowNXNew(std::string_view title, NXContext* nxCtx)
{
std::shared_ptr<IWindow> _WindowNXNew(std::string_view title, NXContext* nxCtx) {
std::shared_ptr<IWindow> ret = std::make_shared<WindowNX>(title, nxCtx);
return ret;
}
}
} // namespace boo

View File

@ -25,21 +25,18 @@ PFN_D3D12_SERIALIZE_ROOT_SIGNATURE D3D12SerializeRootSignaturePROC = nullptr;
pD3DCompile D3DCompilePROC = nullptr;
pD3DCreateBlob D3DCreateBlobPROC = nullptr;
static bool FindBestD3DCompile()
{
static bool FindBestD3DCompile() {
D3DCompilePROC = D3DCompile;
D3DCreateBlobPROC = D3DCreateBlob;
return D3DCompilePROC != nullptr && D3DCreateBlobPROC != nullptr;
}
namespace boo
{
namespace boo {
static logvisor::Module Log("boo::ApplicationUWP");
std::shared_ptr<IWindow> _WindowUWPNew(SystemStringView title, Boo3DAppContextUWP& d3dCtx);
class ApplicationUWP final : public IApplication
{
class ApplicationUWP final : public IApplication {
friend ref class AppView;
IApplicationCallback& m_callback;
const SystemString m_uniqueName;
@ -52,25 +49,17 @@ class ApplicationUWP final : public IApplication
Boo3DAppContextUWP m_3dCtx;
void _deletedWindow(IWindow* window)
{
}
void _deletedWindow(IWindow* window) {}
public:
ApplicationUWP(IApplicationCallback& callback,
SystemStringView uniqueName,
SystemStringView friendlyName,
SystemStringView pname,
const std::vector<SystemString>& args,
bool singleInstance)
: m_callback(callback),
m_uniqueName(uniqueName),
m_friendlyName(friendlyName),
m_pname(pname),
m_args(args),
m_singleInstance(singleInstance)
{
ApplicationUWP(IApplicationCallback& callback, SystemStringView uniqueName, SystemStringView friendlyName,
SystemStringView pname, const std::vector<SystemString>& args, bool singleInstance)
: m_callback(callback)
, m_uniqueName(uniqueName)
, m_friendlyName(friendlyName)
, m_pname(pname)
, m_args(args)
, m_singleInstance(singleInstance) {
typedef HRESULT(WINAPI * CreateDXGIFactory1PROC)(REFIID riid, _COM_Outptr_ void** ppFactory);
CreateDXGIFactory1PROC MyCreateDXGIFactory1 = CreateDXGIFactory1;
@ -80,8 +69,7 @@ public:
no12 = false;
#if _WIN32_WINNT_WIN10
if (!no12)
{
if (!no12) {
if (!FindBestD3DCompile())
Log.report(logvisor::Fatal, "unable to find D3DCompile_[43-47].dll");
@ -97,53 +85,49 @@ public:
/* Adapter */
ComPtr<IDXGIAdapter1> ppAdapter;
for (UINT adapterIndex = 0; ; ++adapterIndex)
{
for (UINT adapterIndex = 0;; ++adapterIndex) {
ComPtr<IDXGIAdapter1> pAdapter;
if (DXGI_ERROR_NOT_FOUND == m_3dCtx.m_ctx12.m_dxFactory->EnumAdapters1(adapterIndex, &pAdapter))
break;
// Check to see if the adapter supports Direct3D 12, but don't create the
// actual device yet.
if (SUCCEEDED(MyD3D12CreateDevice(pAdapter.Get(), D3D_FEATURE_LEVEL_11_0, _uuidof(ID3D12Device), nullptr)))
{
if (SUCCEEDED(MyD3D12CreateDevice(pAdapter.Get(), D3D_FEATURE_LEVEL_11_0, _uuidof(ID3D12Device), nullptr))) {
ppAdapter = std::move(pAdapter);
break;
}
}
/* Create device */
hr = ppAdapter ? MyD3D12CreateDevice(ppAdapter.Get(), D3D_FEATURE_LEVEL_11_0, __uuidof(ID3D12Device), &m_3dCtx.m_ctx12.m_dev) : E_FAIL;
if (!FAILED(hr))
{
hr = ppAdapter ? MyD3D12CreateDevice(ppAdapter.Get(), D3D_FEATURE_LEVEL_11_0, __uuidof(ID3D12Device),
&m_3dCtx.m_ctx12.m_dev)
: E_FAIL;
if (!FAILED(hr)) {
/* Establish loader objects */
if (FAILED(m_3dCtx.m_ctx12.m_dev->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT,
__uuidof(ID3D12CommandAllocator), &m_3dCtx.m_ctx12.m_loadqalloc)))
if (FAILED(m_3dCtx.m_ctx12.m_dev->CreateCommandAllocator(
D3D12_COMMAND_LIST_TYPE_DIRECT, __uuidof(ID3D12CommandAllocator), &m_3dCtx.m_ctx12.m_loadqalloc)))
Log.report(logvisor::Fatal, "unable to create loader allocator");
D3D12_COMMAND_QUEUE_DESC desc =
{
D3D12_COMMAND_LIST_TYPE_DIRECT,
D3D12_COMMAND_QUEUE_PRIORITY_NORMAL,
D3D12_COMMAND_QUEUE_FLAG_NONE
};
if (FAILED(m_3dCtx.m_ctx12.m_dev->CreateCommandQueue(&desc, __uuidof(ID3D12CommandQueue), &m_3dCtx.m_ctx12.m_loadq)))
D3D12_COMMAND_QUEUE_DESC desc = {D3D12_COMMAND_LIST_TYPE_DIRECT, D3D12_COMMAND_QUEUE_PRIORITY_NORMAL,
D3D12_COMMAND_QUEUE_FLAG_NONE};
if (FAILED(m_3dCtx.m_ctx12.m_dev->CreateCommandQueue(&desc, __uuidof(ID3D12CommandQueue),
&m_3dCtx.m_ctx12.m_loadq)))
Log.report(logvisor::Fatal, "unable to create loader queue");
if (FAILED(m_3dCtx.m_ctx12.m_dev->CreateFence(0, D3D12_FENCE_FLAG_NONE, __uuidof(ID3D12Fence), &m_3dCtx.m_ctx12.m_loadfence)))
if (FAILED(m_3dCtx.m_ctx12.m_dev->CreateFence(0, D3D12_FENCE_FLAG_NONE, __uuidof(ID3D12Fence),
&m_3dCtx.m_ctx12.m_loadfence)))
Log.report(logvisor::Fatal, "unable to create loader fence");
m_3dCtx.m_ctx12.m_loadfencehandle = CreateEvent(nullptr, FALSE, FALSE, nullptr);
if (FAILED(m_3dCtx.m_ctx12.m_dev->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, m_3dCtx.m_ctx12.m_loadqalloc.Get(),
nullptr, __uuidof(ID3D12GraphicsCommandList), &m_3dCtx.m_ctx12.m_loadlist)))
if (FAILED(m_3dCtx.m_ctx12.m_dev->CreateCommandList(
0, D3D12_COMMAND_LIST_TYPE_DIRECT, m_3dCtx.m_ctx12.m_loadqalloc.Get(), nullptr,
__uuidof(ID3D12GraphicsCommandList), &m_3dCtx.m_ctx12.m_loadlist)))
Log.report(logvisor::Fatal, "unable to create loader list");
Log.report(logvisor::Info, "initialized D3D12 renderer");
return;
}
else
{
} else {
/* Some Win10 client HW doesn't support D3D12 (despite being supposedly HW-agnostic) */
m_3dCtx.m_ctx12.m_dev.Reset();
m_3dCtx.m_ctx12.m_dxFactory.Reset();
@ -161,15 +145,14 @@ public:
D3D_FEATURE_LEVEL level = D3D_FEATURE_LEVEL_11_0;
ComPtr<ID3D11Device> tempDev;
ComPtr<ID3D11DeviceContext> tempCtx;
if (FAILED(MyD3D11CreateDevice(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, D3D11_CREATE_DEVICE_FLAGS, &level,
1, D3D11_SDK_VERSION, &tempDev, nullptr, &tempCtx)))
if (FAILED(MyD3D11CreateDevice(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, D3D11_CREATE_DEVICE_FLAGS, &level, 1,
D3D11_SDK_VERSION, &tempDev, nullptr, &tempCtx)))
Log.report(logvisor::Fatal, "unable to create D3D11 device");
ComPtr<IDXGIDevice2> device;
if (FAILED(tempDev.As<ID3D11Device1>(&m_3dCtx.m_ctx11.m_dev)) || !m_3dCtx.m_ctx11.m_dev ||
FAILED(tempCtx.As<ID3D11DeviceContext1>(&m_3dCtx.m_ctx11.m_devCtx)) || !m_3dCtx.m_ctx11.m_devCtx ||
FAILED(m_3dCtx.m_ctx11.m_dev.As<IDXGIDevice2>(&device)) || !device)
{
FAILED(m_3dCtx.m_ctx11.m_dev.As<IDXGIDevice2>(&device)) || !device) {
exit(1);
}
@ -197,19 +180,13 @@ public:
Log.report(logvisor::Fatal, "system doesn't support D3D11 or D3D12");
}
EPlatformType getPlatformType() const
{
return EPlatformType::UWP;
}
EPlatformType getPlatformType() const { return EPlatformType::UWP; }
std::thread m_clientThread;
int run()
{
int run() {
/* Spawn client thread */
int clientReturn = 0;
m_clientThread = std::thread([&]()
{
m_clientThread = std::thread([&]() {
std::string thrName = WCSTMBS(getFriendlyName().data()) + " Client Thread";
logvisor::RegisterThreadName(thrName.c_str());
clientReturn = m_callback.appMain(this);
@ -220,99 +197,62 @@ public:
return 0;
}
void quit()
{
void quit() {
m_callback.appQuitting(this);
if (m_clientThread.joinable())
m_clientThread.join();
}
SystemStringView getUniqueName() const
{
return m_uniqueName;
}
SystemStringView getUniqueName() const { return m_uniqueName; }
SystemStringView getFriendlyName() const
{
return m_friendlyName;
}
SystemStringView getFriendlyName() const { return m_friendlyName; }
SystemStringView getProcessName() const
{
return m_pname;
}
SystemStringView getProcessName() const { return m_pname; }
const std::vector<SystemString>& getArgs() const
{
return m_args;
}
const std::vector<SystemString>& getArgs() const { return m_args; }
std::shared_ptr<IWindow> newWindow(SystemStringView title, uint32_t sampleCount)
{
if (!m_issuedWindow)
{
std::shared_ptr<IWindow> newWindow(SystemStringView title, uint32_t sampleCount) {
if (!m_issuedWindow) {
m_issuedWindow = true;
return m_window;
}
return {};
}
void _setWindow(CoreWindow^ window)
{
m_window = _WindowUWPNew(m_friendlyName, m_3dCtx);
}
void _setWindow(CoreWindow ^ window) { m_window = _WindowUWPNew(m_friendlyName, m_3dCtx); }
};
IApplication* APP = NULL;
ref class AppView sealed : public IFrameworkView
{
ref class AppView sealed : public IFrameworkView {
ApplicationUWP m_app;
internal:
AppView(IApplicationCallback& callback,
SystemStringView uniqueName,
SystemStringView friendlyName,
SystemStringView pname,
const std::vector<SystemString>& args,
bool singleInstance)
: m_app(callback, uniqueName, friendlyName, pname, args, singleInstance) { APP = &m_app; }
internal : AppView(IApplicationCallback& callback, SystemStringView uniqueName, SystemStringView friendlyName,
SystemStringView pname, const std::vector<SystemString>& args, bool singleInstance)
: m_app(callback, uniqueName, friendlyName, pname, args, singleInstance) {
APP = &m_app;
}
public:
virtual void Initialize(CoreApplicationView^ applicationView)
{
applicationView->Activated += ref new TypedEventHandler<CoreApplicationView^, IActivatedEventArgs^>(this, &AppView::OnActivated);
virtual void Initialize(CoreApplicationView ^ applicationView) {
applicationView->Activated +=
ref new TypedEventHandler<CoreApplicationView ^, IActivatedEventArgs ^>(this, &AppView::OnActivated);
}
virtual void SetWindow(CoreWindow^ window)
{
m_app._setWindow(window);
}
virtual void SetWindow(CoreWindow ^ window) { m_app._setWindow(window); }
virtual void Load(String^ entryPoint)
{
virtual void Load(String ^ entryPoint) {}
}
virtual void Run() { m_app.run(); }
virtual void Run()
{
m_app.run();
}
virtual void Uninitialize() { m_app.quit(); }
virtual void Uninitialize()
{
m_app.quit();
}
void OnActivated(CoreApplicationView^ applicationView, IActivatedEventArgs^ args)
{
void OnActivated(CoreApplicationView ^ applicationView, IActivatedEventArgs ^ args) {
CoreWindow::GetForCurrentThread()->Activate();
}
};
IFrameworkView^ ViewProvider::CreateView()
{
IFrameworkView ^ ViewProvider::CreateView() {
return ref new AppView(m_appCb, m_uniqueName, m_friendlyName, m_pname, m_args, m_singleInstance);
}
}
} // namespace boo

View File

@ -33,27 +33,21 @@ static LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM l
pD3DCompile D3DCompilePROC = nullptr;
pD3DCreateBlob D3DCreateBlobPROC = nullptr;
static bool FindBestD3DCompile()
{
static bool FindBestD3DCompile() {
HMODULE d3dCompilelib = LoadLibraryW(L"D3DCompiler_47.dll");
if (!d3dCompilelib)
{
if (!d3dCompilelib) {
d3dCompilelib = LoadLibraryW(L"D3DCompiler_46.dll");
if (!d3dCompilelib)
{
if (!d3dCompilelib) {
d3dCompilelib = LoadLibraryW(L"D3DCompiler_45.dll");
if (!d3dCompilelib)
{
if (!d3dCompilelib) {
d3dCompilelib = LoadLibraryW(L"D3DCompiler_44.dll");
if (!d3dCompilelib)
{
if (!d3dCompilelib) {
d3dCompilelib = LoadLibraryW(L"D3DCompiler_43.dll");
}
}
}
}
if (d3dCompilelib)
{
if (d3dCompilelib) {
D3DCompilePROC = (pD3DCompile)GetProcAddress(d3dCompilelib, "D3DCompile");
D3DCreateBlobPROC = (pD3DCreateBlob)GetProcAddress(d3dCompilelib, "D3DCreateBlob");
return D3DCompilePROC != nullptr && D3DCreateBlobPROC != nullptr;
@ -61,15 +55,13 @@ static bool FindBestD3DCompile()
return false;
}
namespace boo
{
namespace boo {
static logvisor::Module Log("boo::ApplicationWin32");
Win32Cursors WIN32_CURSORS;
std::shared_ptr<IWindow> _WindowWin32New(SystemStringView title, Boo3DAppContextWin32& d3dCtx);
class ApplicationWin32 final : public IApplication
{
class ApplicationWin32 final : public IApplication {
IApplicationCallback& m_callback;
const SystemString m_uniqueName;
const SystemString m_friendlyName;
@ -82,29 +74,13 @@ class ApplicationWin32 final : public IApplication
PFN_vkGetInstanceProcAddr m_getVkProc = nullptr;
#endif
void _deletedWindow(IWindow* window)
{
m_allWindows.erase(HWND(window->getPlatformHandle()));
}
void _deletedWindow(IWindow* window) { m_allWindows.erase(HWND(window->getPlatformHandle())); }
public:
ApplicationWin32(IApplicationCallback& callback,
SystemStringView uniqueName,
SystemStringView friendlyName,
SystemStringView pname,
const std::vector<SystemString>& args,
std::string_view gfxApi,
uint32_t samples,
uint32_t anisotropy,
bool deepColor,
bool singleInstance)
: m_callback(callback),
m_uniqueName(uniqueName),
m_friendlyName(friendlyName),
m_pname(pname),
m_args(args)
{
ApplicationWin32(IApplicationCallback& callback, SystemStringView uniqueName, SystemStringView friendlyName,
SystemStringView pname, const std::vector<SystemString>& args, std::string_view gfxApi,
uint32_t samples, uint32_t anisotropy, bool deepColor, bool singleInstance)
: m_callback(callback), m_uniqueName(uniqueName), m_friendlyName(friendlyName), m_pname(pname), m_args(args) {
m_3dCtx.m_ctx11.m_sampleCount = samples;
m_3dCtx.m_ctx11.m_anisotropy = anisotropy;
m_3dCtx.m_ctx11.m_fbFormat = deepColor ? DXGI_FORMAT_R16G16B16A16_FLOAT : DXGI_FORMAT_R8G8B8A8_UNORM;
@ -131,16 +107,13 @@ public:
#if BOO_HAS_VULKAN
bool useVulkan = false;
#endif
if (!gfxApi.empty())
{
if (!gfxApi.empty()) {
#if BOO_HAS_VULKAN
if (!gfxApi.compare("Vulkan"))
{
if (!gfxApi.compare("Vulkan")) {
noD3d = true;
useVulkan = true;
}
if (!gfxApi.compare("OpenGL"))
{
if (!gfxApi.compare("OpenGL")) {
noD3d = true;
useVulkan = false;
}
@ -149,21 +122,17 @@ public:
noD3d = true;
#endif
}
for (const SystemString& arg : args)
{
for (const SystemString& arg : args) {
#if BOO_HAS_VULKAN
if (!arg.compare(L"--d3d11"))
{
if (!arg.compare(L"--d3d11")) {
useVulkan = false;
noD3d = false;
}
if (!arg.compare(L"--vulkan"))
{
if (!arg.compare(L"--vulkan")) {
noD3d = true;
useVulkan = true;
}
if (!arg.compare(L"--gl"))
{
if (!arg.compare(L"--gl")) {
noD3d = true;
useVulkan = false;
}
@ -178,13 +147,13 @@ public:
HMODULE d3d11lib = nullptr;
if (!noD3d)
d3d11lib = LoadLibraryW(L"D3D11.dll");
if (d3d11lib)
{
if (d3d11lib) {
if (!FindBestD3DCompile())
Log.report(logvisor::Fatal, "unable to find D3DCompile_[43-47].dll");
/* Create device proc */
PFN_D3D11_CREATE_DEVICE MyD3D11CreateDevice = (PFN_D3D11_CREATE_DEVICE)GetProcAddress(d3d11lib, "D3D11CreateDevice");
PFN_D3D11_CREATE_DEVICE MyD3D11CreateDevice =
(PFN_D3D11_CREATE_DEVICE)GetProcAddress(d3d11lib, "D3D11CreateDevice");
if (!MyD3D11CreateDevice)
Log.report(logvisor::Fatal, "unable to find D3D11CreateDevice in D3D11.dll");
@ -192,16 +161,16 @@ public:
D3D_FEATURE_LEVEL level = D3D_FEATURE_LEVEL_11_0;
ComPtr<ID3D11Device> tempDev;
ComPtr<ID3D11DeviceContext> tempCtx;
if (FAILED(MyD3D11CreateDevice(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, D3D11_CREATE_DEVICE_FLAGS, &level,
1, D3D11_SDK_VERSION, &tempDev, nullptr, &tempCtx)))
if (FAILED(MyD3D11CreateDevice(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, D3D11_CREATE_DEVICE_FLAGS, &level, 1,
D3D11_SDK_VERSION, &tempDev, nullptr, &tempCtx)))
Log.report(logvisor::Fatal, "unable to create D3D11 device");
ComPtr<IDXGIDevice2> device;
if (FAILED(tempDev.As<ID3D11Device1>(&m_3dCtx.m_ctx11.m_dev)) || !m_3dCtx.m_ctx11.m_dev ||
FAILED(tempCtx.As<ID3D11DeviceContext1>(&m_3dCtx.m_ctx11.m_devCtx)) || !m_3dCtx.m_ctx11.m_devCtx ||
FAILED(m_3dCtx.m_ctx11.m_dev.As<IDXGIDevice2>(&device)) || !device)
{
MessageBoxW(nullptr, L"Windows 7 users should install 'Platform Update for Windows 7':\n"
FAILED(m_3dCtx.m_ctx11.m_dev.As<IDXGIDevice2>(&device)) || !device) {
MessageBoxW(nullptr,
L"Windows 7 users should install 'Platform Update for Windows 7':\n"
L"https://www.microsoft.com/en-us/download/details.aspx?id=36805",
L"IDXGIDevice2 interface error", MB_OK | MB_ICONERROR);
exit(1);
@ -250,22 +219,16 @@ public:
}
#if BOO_HAS_VULKAN
if (useVulkan)
{
if (useVulkan) {
HMODULE vulkanLib = LoadLibraryW(L"vulkan-1.dll");
if (vulkanLib)
{
if (vulkanLib) {
m_getVkProc = (PFN_vkGetInstanceProcAddr)GetProcAddress(vulkanLib, "vkGetInstanceProcAddr");
if (m_getVkProc)
{
if (m_getVkProc) {
/* Check device support for vulkan */
if (g_VulkanContext.m_instance == VK_NULL_HANDLE)
{
if (g_VulkanContext.m_instance == VK_NULL_HANDLE) {
auto appName = getUniqueName();
if (g_VulkanContext.initVulkan(WCSTMBS(appName.data()).c_str(), m_getVkProc))
{
if (g_VulkanContext.enumerateDevices())
{
if (g_VulkanContext.initVulkan(WCSTMBS(appName.data()).c_str(), m_getVkProc)) {
if (g_VulkanContext.enumerateDevices()) {
/* Obtain DXGI Factory */
HRESULT hr = MyCreateDXGIFactory1(__uuidof(IDXGIFactory1), &m_3dCtx.m_vulkanDxFactory);
if (FAILED(hr))
@ -295,24 +258,20 @@ public:
Log.report(logvisor::Fatal, "system doesn't support Vulkan, D3D11, or OpenGL");
}
EPlatformType getPlatformType() const
{
return EPlatformType::Win32;
}
EPlatformType getPlatformType() const { return EPlatformType::Win32; }
LRESULT winHwndHandler(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
LRESULT winHwndHandler(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
/* Lookup boo window instance */
auto search = m_allWindows.find(hwnd);
if (search == m_allWindows.end())
return DefWindowProc(hwnd, uMsg, wParam, lParam);;
return DefWindowProc(hwnd, uMsg, wParam, lParam);
;
std::shared_ptr<IWindow> window = search->second.lock();
if (!window)
return DefWindowProc(hwnd, uMsg, wParam, lParam);
switch (uMsg)
{
switch (uMsg) {
case WM_CREATE:
return 0;
@ -342,8 +301,7 @@ public:
case WM_MOUSEWHEEL:
case WM_MOUSEHWHEEL:
case WM_CHAR:
case WM_UNICHAR:
{
case WM_UNICHAR: {
HWNDEvent eventData(uMsg, wParam, lParam);
window->_incomingEvent(&eventData);
}
@ -354,54 +312,44 @@ public:
}
template <class W>
static void DoSetFullscreen(W& win, bool fs)
{
static void DoSetFullscreen(W& win, bool fs) {
std::lock_guard<std::mutex> lk(g_nwmt);
if (fs)
{
if (fs) {
win.m_fsStyle = GetWindowLong(win.m_hwnd, GWL_STYLE);
win.m_fsExStyle = GetWindowLong(win.m_hwnd, GWL_EXSTYLE);
GetWindowRect(win.m_hwnd, &win.m_fsRect);
SetWindowLong(win.m_hwnd, GWL_STYLE,
win.m_fsStyle & ~(WS_CAPTION | WS_THICKFRAME));
SetWindowLong(win.m_hwnd, GWL_STYLE, win.m_fsStyle & ~(WS_CAPTION | WS_THICKFRAME));
SetWindowLong(win.m_hwnd, GWL_EXSTYLE,
win.m_fsExStyle & ~(WS_EX_DLGMODALFRAME |
WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE | WS_EX_STATICEDGE));
win.m_fsExStyle & ~(WS_EX_DLGMODALFRAME | WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE | WS_EX_STATICEDGE));
MONITORINFO monitor_info;
monitor_info.cbSize = sizeof(monitor_info);
GetMonitorInfo(MonitorFromWindow(win.m_hwnd, MONITOR_DEFAULTTONEAREST),
&monitor_info);
GetMonitorInfo(MonitorFromWindow(win.m_hwnd, MONITOR_DEFAULTTONEAREST), &monitor_info);
SetWindowPos(win.m_hwnd, NULL, monitor_info.rcMonitor.left, monitor_info.rcMonitor.top,
monitor_info.rcMonitor.right - monitor_info.rcMonitor.left,
monitor_info.rcMonitor.bottom - monitor_info.rcMonitor.top,
SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED);
win.m_fs = true;
}
else
{
} else {
SetWindowLong(win.m_hwnd, GWL_STYLE, win.m_fsStyle);
SetWindowLong(win.m_hwnd, GWL_EXSTYLE, win.m_fsExStyle);
SetWindowPos(win.m_hwnd, NULL, win.m_fsRect.left, win.m_fsRect.top,
win.m_fsRect.right - win.m_fsRect.left, win.m_fsRect.bottom - win.m_fsRect.top,
SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED);
SetWindowPos(win.m_hwnd, NULL, win.m_fsRect.left, win.m_fsRect.top, win.m_fsRect.right - win.m_fsRect.left,
win.m_fsRect.bottom - win.m_fsRect.top, SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED);
win.m_fs = false;
}
g_nwcv.notify_one();
}
int run()
{
int run() {
g_mainThreadId = GetCurrentThreadId();
/* Spawn client thread */
int clientReturn = 0;
std::thread clientThread([&]()
{
std::thread clientThread([&]() {
std::string thrName = WCSTMBS(getFriendlyName().data()) + " Client Thread";
logvisor::RegisterThreadName(thrName.c_str());
CoInitializeEx(nullptr, COINIT_MULTITHREADED | COINIT_DISABLE_OLE1DDE);
@ -411,15 +359,11 @@ public:
/* Pump messages */
MSG msg = {0};
while (GetMessage(&msg, NULL, 0, 0))
{
if (!msg.hwnd)
{
while (GetMessage(&msg, NULL, 0, 0)) {
if (!msg.hwnd) {
/* PostThreadMessage events */
switch (msg.message)
{
case WM_USER:
{
switch (msg.message) {
case WM_USER: {
/* New-window message (coalesced onto main thread) */
std::lock_guard<std::mutex> lk(g_nwmt);
SystemStringView* title = reinterpret_cast<SystemStringView*>(msg.wParam);
@ -453,7 +397,8 @@ public:
DoSetFullscreen(*reinterpret_cast<boo::VulkanContext::Window*>(msg.wParam), msg.lParam);
continue;
#endif
default: break;
default:
break;
}
}
TranslateMessage(&msg);
@ -465,38 +410,23 @@ public:
return clientReturn;
}
~ApplicationWin32()
{
~ApplicationWin32() {
for (auto& p : m_allWindows)
if (auto w = p.second.lock())
w->_cleanup();
}
SystemStringView getUniqueName() const
{
return m_uniqueName;
}
SystemStringView getUniqueName() const { return m_uniqueName; }
SystemStringView getFriendlyName() const
{
return m_friendlyName;
}
SystemStringView getFriendlyName() const { return m_friendlyName; }
SystemStringView getProcessName() const
{
return m_pname;
}
SystemStringView getProcessName() const { return m_pname; }
const std::vector<SystemString>& getArgs() const
{
return m_args;
}
const std::vector<SystemString>& getArgs() const { return m_args; }
std::shared_ptr<IWindow> m_mwret;
std::shared_ptr<IWindow> newWindow(SystemStringView title)
{
if (GetCurrentThreadId() != g_mainThreadId)
{
std::shared_ptr<IWindow> newWindow(SystemStringView title) {
if (GetCurrentThreadId() != g_mainThreadId) {
std::unique_lock<std::mutex> lk(g_nwmt);
if (!PostThreadMessageW(g_mainThreadId, WM_USER, WPARAM(&title), 0))
Log.report(logvisor::Fatal, "PostThreadMessage error");
@ -514,32 +444,22 @@ public:
};
IApplication* APP = NULL;
int ApplicationRun(IApplication::EPlatformType platform,
IApplicationCallback& cb,
SystemStringView uniqueName,
SystemStringView friendlyName,
SystemStringView pname,
const std::vector<SystemString>& args,
std::string_view gfxApi,
uint32_t samples,
uint32_t anisotropy,
bool deepColor,
bool singleInstance)
{
int ApplicationRun(IApplication::EPlatformType platform, IApplicationCallback& cb, SystemStringView uniqueName,
SystemStringView friendlyName, SystemStringView pname, const std::vector<SystemString>& args,
std::string_view gfxApi, uint32_t samples, uint32_t anisotropy, bool deepColor,
bool singleInstance) {
std::string thrName = WCSTMBS(friendlyName.data()) + " Main Thread";
logvisor::RegisterThreadName(thrName.c_str());
if (APP)
return 1;
if (platform != IApplication::EPlatformType::Win32 &&
platform != IApplication::EPlatformType::Auto)
if (platform != IApplication::EPlatformType::Win32 && platform != IApplication::EPlatformType::Auto)
return 1;
#if _WIN32_WINNT_WINBLUE
/* HI-DPI support */
HMODULE shcoreLib = LoadLibraryW(L"Shcore.dll");
if (shcoreLib)
MyGetScaleFactorForMonitor =
(PFN_GetScaleFactorForMonitor)GetProcAddress(shcoreLib, "GetScaleFactorForMonitor");
MyGetScaleFactorForMonitor = (PFN_GetScaleFactorForMonitor)GetProcAddress(shcoreLib, "GetScaleFactorForMonitor");
#endif
WIN32_CURSORS.m_arrow = LoadCursor(nullptr, IDC_ARROW);
@ -550,43 +470,26 @@ int ApplicationRun(IApplication::EPlatformType platform,
WIN32_CURSORS.m_wait = LoadCursor(nullptr, IDC_WAIT);
/* One class for *all* boo windows */
WNDCLASS wndClass =
{
0,
WindowProc,
0,
0,
GetModuleHandle(nullptr),
0,
0,
0,
0,
L"BooWindow"
};
WNDCLASS wndClass = {0, WindowProc, 0, 0, GetModuleHandle(nullptr), 0, 0, 0, 0, L"BooWindow"};
wndClass.hIcon = LoadIconW(wndClass.hInstance, MAKEINTRESOURCEW(101));
wndClass.hCursor = WIN32_CURSORS.m_arrow;
RegisterClassW(&wndClass);
APP = new ApplicationWin32(cb, uniqueName, friendlyName, pname, args,
gfxApi, samples, anisotropy, deepColor, singleInstance);
APP = new ApplicationWin32(cb, uniqueName, friendlyName, pname, args, gfxApi, samples, anisotropy, deepColor,
singleInstance);
int ret = APP->run();
delete APP;
APP = nullptr;
return ret;
}
}
} // namespace boo
static const DEV_BROADCAST_DEVICEINTERFACE HOTPLUG_CONF =
{
sizeof(DEV_BROADCAST_DEVICEINTERFACE),
DBT_DEVTYP_DEVICEINTERFACE
};
static const DEV_BROADCAST_DEVICEINTERFACE HOTPLUG_CONF = {sizeof(DEV_BROADCAST_DEVICEINTERFACE),
DBT_DEVTYP_DEVICEINTERFACE};
static bool HOTPLUG_REGISTERED = false;
static LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
if (!HOTPLUG_REGISTERED && uMsg == WM_CREATE)
{
static LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
if (!HOTPLUG_REGISTERED && uMsg == WM_CREATE) {
/* Register hotplug notification with windows */
RegisterDeviceNotification(hwnd, (LPVOID)&HOTPLUG_CONF,
DEVICE_NOTIFY_WINDOW_HANDLE | DEVICE_NOTIFY_ALL_INTERFACE_CLASSES);
@ -594,4 +497,3 @@ static LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM l
}
return static_cast<boo::ApplicationWin32*>(boo::APP)->winHwndHandler(hwnd, uMsg, wParam, lParam);
}

Some files were not shown because too many files have changed in this diff Show More