Added Daybreak, a system updater homebrew (#1073)

* Implemented a system updater homebrew (titled Daybreak)

* git subrepo pull ./troposphere/daybreak/nanovg

subrepo:
  subdir:   "troposphere/daybreak/nanovg"
  merged:   "c197ba2f"
upstream:
  origin:   "https://github.com/Adubbz/nanovg-deko.git"
  branch:   "master"
  commit:   "c197ba2f"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???" (+1 squashed commits)

Squashed commits:

[232dc943] git subrepo clone https://github.com/Adubbz/nanovg-deko.git troposphere/daybreak/nanovg

subrepo:
  subdir:   "troposphere/daybreak/nanovg"
  merged:   "52bb784b"
upstream:
  origin:   "https://github.com/Adubbz/nanovg-deko.git"
  branch:   "master"
  commit:   "52bb784b"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"

* daybreak: switch to using hiddbg for home blocking (+1 squashed commits)

Squashed commits:

[4bfc7b0d] daybreak: block the home button during installation
This commit is contained in:
Adubbz
2020-07-08 10:07:00 +10:00
committed by GitHub
parent b08ccd7341
commit 94eb2195d3
48 changed files with 24243 additions and 1 deletions

View File

@@ -0,0 +1,207 @@
#pragma once
#include <deko3d.hpp>
#include <map>
#include <memory>
#include <vector>
#include "framework/CDescriptorSet.h"
#include "framework/CMemPool.h"
#include "framework/CShader.h"
#include "framework/CCmdMemRing.h"
#include "nanovg.h"
// Create flags
enum NVGcreateFlags {
// Flag indicating if geometry based anti-aliasing is used (may not be needed when using MSAA).
NVG_ANTIALIAS = 1<<0,
// Flag indicating if strokes should be drawn using stencil buffer. The rendering will be a little
// slower, but path overlaps (i.e. self-intersecting or sharp turns) will be drawn just once.
NVG_STENCIL_STROKES = 1<<1,
// Flag indicating that additional debug checks are done.
NVG_DEBUG = 1<<2,
};
enum DKNVGuniformLoc
{
DKNVG_LOC_VIEWSIZE,
DKNVG_LOC_TEX,
DKNVG_LOC_FRAG,
DKNVG_MAX_LOCS
};
enum VKNVGshaderType {
NSVG_SHADER_FILLGRAD,
NSVG_SHADER_FILLIMG,
NSVG_SHADER_SIMPLE,
NSVG_SHADER_IMG
};
struct DKNVGtextureDescriptor {
int width, height;
int type;
int flags;
};
struct DKNVGblend {
int srcRGB;
int dstRGB;
int srcAlpha;
int dstAlpha;
};
enum DKNVGcallType {
DKNVG_NONE = 0,
DKNVG_FILL,
DKNVG_CONVEXFILL,
DKNVG_STROKE,
DKNVG_TRIANGLES,
};
struct DKNVGcall {
int type;
int image;
int pathOffset;
int pathCount;
int triangleOffset;
int triangleCount;
int uniformOffset;
DKNVGblend blendFunc;
};
struct DKNVGpath {
int fillOffset;
int fillCount;
int strokeOffset;
int strokeCount;
};
struct DKNVGfragUniforms {
float scissorMat[12]; // matrices are actually 3 vec4s
float paintMat[12];
struct NVGcolor innerCol;
struct NVGcolor outerCol;
float scissorExt[2];
float scissorScale[2];
float extent[2];
float radius;
float feather;
float strokeMult;
float strokeThr;
int texType;
int type;
};
namespace nvg {
class DkRenderer;
}
struct DKNVGcontext {
nvg::DkRenderer *renderer;
float view[2];
int fragSize;
int flags;
// Per frame buffers
DKNVGcall* calls;
int ccalls;
int ncalls;
DKNVGpath* paths;
int cpaths;
int npaths;
struct NVGvertex* verts;
int cverts;
int nverts;
unsigned char* uniforms;
int cuniforms;
int nuniforms;
};
namespace nvg {
class Texture {
private:
const int m_id;
dk::Image m_image;
dk::ImageDescriptor m_image_descriptor;
CMemPool::Handle m_image_mem;
DKNVGtextureDescriptor m_texture_descriptor;
public:
Texture(int id);
~Texture();
void Initialize(CMemPool &image_pool, CMemPool &scratch_pool, dk::Device device, dk::Queue transfer_queue, int type, int w, int h, int image_flags, const u8 *data);
void Update(CMemPool &image_pool, CMemPool &scratch_pool, dk::Device device, dk::Queue transfer_queue, int type, int w, int h, int image_flags, const u8 *data);
int GetId();
const DKNVGtextureDescriptor &GetDescriptor();
dk::Image &GetImage();
dk::ImageDescriptor &GetImageDescriptor();
};
class DkRenderer {
private:
enum SamplerType : u8 {
SamplerType_MipFilter = 1 << 0,
SamplerType_Nearest = 1 << 1,
SamplerType_RepeatX = 1 << 2,
SamplerType_RepeatY = 1 << 3,
SamplerType_Total = 0x10,
};
private:
static constexpr size_t DynamicCmdSize = 0x20000;
static constexpr size_t FragmentUniformSize = sizeof(DKNVGfragUniforms) + 4 - sizeof(DKNVGfragUniforms) % 4;
static constexpr size_t MaxImages = 0x1000;
/* From the application. */
u32 m_view_width;
u32 m_view_height;
dk::Device m_device;
dk::Queue m_queue;
CMemPool &m_image_mem_pool;
CMemPool &m_code_mem_pool;
CMemPool &m_data_mem_pool;
/* State. */
dk::UniqueCmdBuf m_dyn_cmd_buf;
CCmdMemRing<1> m_dyn_cmd_mem;
std::optional<CMemPool::Handle> m_vertex_buffer;
CShader m_vertex_shader;
CShader m_fragment_shader;
CMemPool::Handle m_view_uniform_buffer;
CMemPool::Handle m_frag_uniform_buffer;
u32 m_next_texture_id = 1;
std::vector<std::shared_ptr<Texture>> m_textures;
CDescriptorSet<MaxImages> m_image_descriptor_set;
CDescriptorSet<SamplerType_Total> m_sampler_descriptor_set;
std::array<int, MaxImages> m_image_descriptor_mappings;
int m_last_image_descriptor = 0;
int AcquireImageDescriptor(std::shared_ptr<Texture> texture, int image);
void FreeImageDescriptor(int image);
void SetUniforms(const DKNVGcontext &ctx, int offset, int image);
void UpdateVertexBuffer(const void *data, size_t size);
void DrawFill(const DKNVGcontext &ctx, const DKNVGcall &call);
void DrawConvexFill(const DKNVGcontext &ctx, const DKNVGcall &call);
void DrawStroke(const DKNVGcontext &ctx, const DKNVGcall &call);
void DrawTriangles(const DKNVGcontext &ctx, const DKNVGcall &call);
std::shared_ptr<Texture> FindTexture(int id);
public:
DkRenderer(unsigned int view_width, unsigned int view_height, dk::Device device, dk::Queue queue, CMemPool &image_mem_pool, CMemPool &code_mem_pool, CMemPool &data_mem_pool);
~DkRenderer();
int Create(DKNVGcontext &ctx);
int CreateTexture(const DKNVGcontext &ctx, int type, int w, int h, int image_flags, const u8 *data);
int DeleteTexture(const DKNVGcontext &ctx, int id);
int UpdateTexture(const DKNVGcontext &ctx, int id, int x, int y, int w, int h, const u8 *data);
int GetTextureSize(const DKNVGcontext &ctx, int id, int *w, int *h);
const DKNVGtextureDescriptor *GetTextureDescriptor(const DKNVGcontext &ctx, int id);
void Flush(DKNVGcontext &ctx);
};
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,38 @@
/*
** Sample Framework for deko3d Applications
** CApplication.h: Wrapper class containing common application boilerplate
*/
#pragma once
#include "common.h"
class CApplication
{
protected:
virtual void onFocusState(AppletFocusState) { }
virtual void onOperationMode(AppletOperationMode) { }
virtual bool onFrame(u64) { return true; }
public:
CApplication();
~CApplication();
void run();
static constexpr void chooseFramebufferSize(uint32_t& width, uint32_t& height, AppletOperationMode mode);
};
constexpr void CApplication::chooseFramebufferSize(uint32_t& width, uint32_t& height, AppletOperationMode mode)
{
switch (mode)
{
default:
case AppletOperationMode_Handheld:
width = 1280;
height = 720;
break;
case AppletOperationMode_Docked:
width = 1920;
height = 1080;
break;
}
}

View File

@@ -0,0 +1,57 @@
/*
** Sample Framework for deko3d Applications
** CCmdMemRing.h: Memory provider class for dynamic command buffers
*/
#pragma once
#include "common.h"
#include "CMemPool.h"
template <unsigned NumSlices>
class CCmdMemRing
{
static_assert(NumSlices > 0, "Need a non-zero number of slices...");
CMemPool::Handle m_mem;
unsigned m_curSlice;
dk::Fence m_fences[NumSlices];
public:
CCmdMemRing() : m_mem{}, m_curSlice{}, m_fences{} { }
~CCmdMemRing()
{
m_mem.destroy();
}
bool allocate(CMemPool& pool, uint32_t sliceSize)
{
sliceSize = (sliceSize + DK_CMDMEM_ALIGNMENT - 1) &~ (DK_CMDMEM_ALIGNMENT - 1);
m_mem = pool.allocate(NumSlices*sliceSize);
return m_mem;
}
void begin(dk::CmdBuf cmdbuf)
{
// Clear/reset the command buffer, which also destroys all command list handles
// (but remember: it does *not* in fact destroy the command data)
cmdbuf.clear();
// Wait for the current slice of memory to be available, and feed it to the command buffer
uint32_t sliceSize = m_mem.getSize() / NumSlices;
m_fences[m_curSlice].wait();
// Feed the memory to the command buffer
cmdbuf.addMemory(m_mem.getMemBlock(), m_mem.getOffset() + m_curSlice * sliceSize, sliceSize);
}
DkCmdList end(dk::CmdBuf cmdbuf)
{
// Signal the fence corresponding to the current slice; so that in the future when we want
// to use it again, we can wait for the completion of the commands we've just submitted
// (and as such we don't overwrite in-flight command data with new one)
cmdbuf.signalFence(m_fences[m_curSlice]);
// Advance the current slice counter; wrapping around when we reach the end
m_curSlice = (m_curSlice + 1) % NumSlices;
// Finish off the command list, returning it to the caller
return cmdbuf.finishList();
}
};

View File

@@ -0,0 +1,71 @@
/*
** Sample Framework for deko3d Applications
** CDescriptorSet.h: Image/Sampler descriptor set class
*/
#pragma once
#include "common.h"
#include "CMemPool.h"
template <unsigned NumDescriptors>
class CDescriptorSet
{
static_assert(NumDescriptors > 0, "Need a non-zero number of descriptors...");
static_assert(sizeof(DkImageDescriptor) == sizeof(DkSamplerDescriptor), "shouldn't happen");
static_assert(DK_IMAGE_DESCRIPTOR_ALIGNMENT == DK_SAMPLER_DESCRIPTOR_ALIGNMENT, "shouldn't happen");
static constexpr size_t DescriptorSize = sizeof(DkImageDescriptor);
static constexpr size_t DescriptorAlign = DK_IMAGE_DESCRIPTOR_ALIGNMENT;
CMemPool::Handle m_mem;
public:
CDescriptorSet() : m_mem{} { }
~CDescriptorSet()
{
m_mem.destroy();
}
bool allocate(CMemPool& pool)
{
m_mem = pool.allocate(NumDescriptors*DescriptorSize, DescriptorAlign);
return m_mem;
}
void bindForImages(dk::CmdBuf cmdbuf)
{
cmdbuf.bindImageDescriptorSet(m_mem.getGpuAddr(), NumDescriptors);
}
void bindForSamplers(dk::CmdBuf cmdbuf)
{
cmdbuf.bindSamplerDescriptorSet(m_mem.getGpuAddr(), NumDescriptors);
}
template <typename T>
void update(dk::CmdBuf cmdbuf, uint32_t id, T const& descriptor)
{
static_assert(sizeof(T) == DescriptorSize);
cmdbuf.pushData(m_mem.getGpuAddr() + id*DescriptorSize, &descriptor, DescriptorSize);
}
template <typename T, size_t N>
void update(dk::CmdBuf cmdbuf, uint32_t id, std::array<T, N> const& descriptors)
{
static_assert(sizeof(T) == DescriptorSize);
cmdbuf.pushData(m_mem.getGpuAddr() + id*DescriptorSize, descriptors.data(), descriptors.size()*DescriptorSize);
}
#ifdef DK_HPP_SUPPORT_VECTOR
template <typename T, typename Allocator = std::allocator<T>>
void update(dk::CmdBuf cmdbuf, uint32_t id, std::vector<T,Allocator> const& descriptors)
{
static_assert(sizeof(T) == DescriptorSize);
cmdbuf.pushData(m_mem.getGpuAddr() + id*DescriptorSize, descriptors.data(), descriptors.size()*DescriptorSize);
}
#endif
template <typename T>
void update(dk::CmdBuf cmdbuf, uint32_t id, std::initializer_list<T const> const& descriptors)
{
static_assert(sizeof(T) == DescriptorSize);
cmdbuf.pushData(m_mem.getGpuAddr() + id*DescriptorSize, descriptors.data(), descriptors.size()*DescriptorSize);
}
};

View File

@@ -0,0 +1,37 @@
/*
** Sample Framework for deko3d Applications
** CExternalImage.h: Utility class for loading images from the filesystem
*/
#pragma once
#include "common.h"
#include "CMemPool.h"
class CExternalImage
{
dk::Image m_image;
dk::ImageDescriptor m_descriptor;
CMemPool::Handle m_mem;
public:
CExternalImage() : m_image{}, m_descriptor{}, m_mem{} { }
~CExternalImage()
{
m_mem.destroy();
}
constexpr operator bool() const
{
return m_mem;
}
constexpr dk::Image& get()
{
return m_image;
}
constexpr dk::ImageDescriptor const& getDescriptor() const
{
return m_descriptor;
}
bool load(CMemPool& imagePool, CMemPool& scratchPool, dk::Device device, dk::Queue transferQueue, const char* path, uint32_t width, uint32_t height, DkImageFormat format, uint32_t flags = 0);
};

View File

@@ -0,0 +1,119 @@
/*
** Sample Framework for deko3d Applications
** CIntrusiveList.h: Intrusive doubly-linked list helper class
*/
#pragma once
#include "common.h"
template <typename T>
struct CIntrusiveListNode
{
T *m_next, *m_prev;
constexpr CIntrusiveListNode() : m_next{}, m_prev{} { }
constexpr operator bool() const { return m_next || m_prev; }
};
template <typename T, CIntrusiveListNode<T> T::* node_ptr>
class CIntrusiveList
{
T *m_first, *m_last;
public:
constexpr CIntrusiveList() : m_first{}, m_last{} { }
constexpr T* first() const { return m_first; }
constexpr T* last() const { return m_last; }
constexpr bool empty() const { return !m_first; }
constexpr void clear() { m_first = m_last = nullptr; }
constexpr bool isLinked(T* obj) const { return obj->*node_ptr || m_first == obj; }
constexpr T* prev(T* obj) const { return (obj->*node_ptr).m_prev; }
constexpr T* next(T* obj) const { return (obj->*node_ptr).m_next; }
void add(T* obj)
{
return addBefore(nullptr, obj);
}
void addBefore(T* pos, T* obj)
{
auto& node = obj->*node_ptr;
node.m_next = pos;
node.m_prev = pos ? (pos->*node_ptr).m_prev : m_last;
if (pos)
(pos->*node_ptr).m_prev = obj;
else
m_last = obj;
if (node.m_prev)
(node.m_prev->*node_ptr).m_next = obj;
else
m_first = obj;
}
void addAfter(T* pos, T* obj)
{
auto& node = obj->*node_ptr;
node.m_next = pos ? (pos->*node_ptr).m_next : m_first;
node.m_prev = pos;
if (pos)
(pos->*node_ptr).m_next = obj;
else
m_first = obj;
if (node.m_next)
(node.m_next->*node_ptr).m_prev = obj;
else
m_last = obj;
}
T* pop()
{
T* ret = m_first;
if (ret)
{
m_first = (ret->*node_ptr).m_next;
if (m_first)
(m_first->*node_ptr).m_prev = nullptr;
else
m_last = nullptr;
}
return ret;
}
void remove(T* obj)
{
auto& node = obj->*node_ptr;
if (node.m_prev)
{
(node.m_prev->*node_ptr).m_next = node.m_next;
if (node.m_next)
(node.m_next->*node_ptr).m_prev = node.m_prev;
else
m_last = node.m_prev;
} else
{
m_first = node.m_next;
if (m_first)
(m_first->*node_ptr).m_prev = nullptr;
else
m_last = nullptr;
}
node.m_next = node.m_prev = 0;
}
template <typename L>
void iterate(L lambda) const
{
T* next = nullptr;
for (T* cur = m_first; cur; cur = next)
{
next = (cur->*node_ptr).m_next;
lambda(cur);
}
}
};

View File

@@ -0,0 +1,250 @@
/*
** Sample Framework for deko3d Applications
** CIntrusiveTree.h: Intrusive red-black tree helper class
*/
#pragma once
#include "common.h"
#include <functional>
struct CIntrusiveTreeNode
{
enum Color
{
Red,
Black,
};
enum Leaf
{
Left,
Right,
};
private:
uintptr_t m_parent_color;
CIntrusiveTreeNode* m_children[2];
public:
constexpr CIntrusiveTreeNode() : m_parent_color{}, m_children{} { }
constexpr CIntrusiveTreeNode* getParent() const
{
return reinterpret_cast<CIntrusiveTreeNode*>(m_parent_color &~ 1);
}
void setParent(CIntrusiveTreeNode* parent)
{
m_parent_color = (m_parent_color & 1) | reinterpret_cast<uintptr_t>(parent);
}
constexpr Color getColor() const
{
return static_cast<Color>(m_parent_color & 1);
}
void setColor(Color color)
{
m_parent_color = (m_parent_color &~ 1) | static_cast<uintptr_t>(color);
}
constexpr CIntrusiveTreeNode*& child(Leaf leaf)
{
return m_children[leaf];
}
constexpr CIntrusiveTreeNode* const& child(Leaf leaf) const
{
return m_children[leaf];
}
//--------------------------------------
constexpr bool isRed() const { return getColor() == Red; }
constexpr bool isBlack() const { return getColor() == Black; }
void setRed() { setColor(Red); }
void setBlack() { setColor(Black); }
constexpr CIntrusiveTreeNode*& left() { return child(Left); }
constexpr CIntrusiveTreeNode*& right() { return child(Right); }
constexpr CIntrusiveTreeNode* const& left() const { return child(Left); }
constexpr CIntrusiveTreeNode* const& right() const { return child(Right); }
};
NX_CONSTEXPR CIntrusiveTreeNode::Leaf operator!(CIntrusiveTreeNode::Leaf val) noexcept
{
return static_cast<CIntrusiveTreeNode::Leaf>(!static_cast<unsigned>(val));
}
class CIntrusiveTreeBase
{
using N = CIntrusiveTreeNode;
void rotate(N* node, N::Leaf leaf);
void recolor(N* parent, N* node);
protected:
N* m_root;
constexpr CIntrusiveTreeBase() : m_root{} { }
N* walk(N* node, N::Leaf leaf) const;
void insert(N* node, N* parent);
void remove(N* node);
N* minmax(N::Leaf leaf) const
{
N* p = m_root;
if (!p)
return nullptr;
while (p->child(leaf))
p = p->child(leaf);
return p;
}
template <typename H>
N*& navigate(N*& node, N*& parent, N::Leaf leafOnEqual, H helm) const
{
node = nullptr;
parent = nullptr;
N** point = const_cast<N**>(&m_root);
while (*point)
{
int direction = helm(*point);
parent = *point;
if (direction < 0)
point = &(*point)->left();
else if (direction > 0)
point = &(*point)->right();
else
{
node = *point;
point = &(*point)->child(leafOnEqual);
}
}
return *point;
}
};
template <typename ClassT, typename MemberT>
constexpr ClassT* parent_obj(MemberT* member, MemberT ClassT::* ptr)
{
union whatever
{
MemberT ClassT::* ptr;
intptr_t offset;
};
// This is technically UB, but basically every compiler worth using admits it as an extension
return (ClassT*)((intptr_t)member - whatever{ptr}.offset);
}
template <
typename T,
CIntrusiveTreeNode T::* node_ptr,
typename Comparator = std::less<>
>
class CIntrusiveTree final : protected CIntrusiveTreeBase
{
using N = CIntrusiveTreeNode;
static constexpr T* toType(N* m)
{
return m ? parent_obj(m, node_ptr) : nullptr;
}
static constexpr N* toNode(T* m)
{
return m ? &(m->*node_ptr) : nullptr;
}
template <typename A, typename B>
static int compare(A const& a, B const& b)
{
Comparator comp;
if (comp(a, b))
return -1;
if (comp(b, a))
return 1;
return 0;
}
public:
constexpr CIntrusiveTree() : CIntrusiveTreeBase{} { }
T* first() const { return toType(minmax(N::Left)); }
T* last() const { return toType(minmax(N::Right)); }
bool empty() const { return m_root != nullptr; }
void clear() { m_root = nullptr; }
T* prev(T* node) const { return toType(walk(toNode(node), N::Left)); }
T* next(T* node) const { return toType(walk(toNode(node), N::Right)); }
enum SearchMode
{
Exact = 0,
LowerBound = 1,
UpperBound = 2,
};
template <typename Lambda>
T* search(SearchMode mode, Lambda lambda) const
{
N *node, *parent;
N*& point = navigate(node, parent,
mode != UpperBound ? N::Left : N::Right,
[&lambda](N* curnode) { return lambda(toType(curnode)); });
switch (mode)
{
default:
case Exact:
break;
case LowerBound:
if (!node && parent)
{
if (&parent->left() == &point)
node = parent;
else
node = walk(parent, N::Right);
}
break;
case UpperBound:
if (node)
node = walk(node, N::Right);
else if (parent)
{
if (&parent->right() == &point)
node = walk(parent, N::Right);
else
node = parent;
}
break;
}
return toType(node);
}
template <typename K>
T* find(K const& key, SearchMode mode = Exact) const
{
return search(mode, [&key](T* obj) { return compare(key, *obj); });
}
T* insert(T* obj, bool allow_dupes = false)
{
N *node, *parent;
N*& point = navigate(node, parent, N::Right,
[obj](N* curnode) { return compare(*obj, *toType(curnode)); });
if (node && !allow_dupes)
return toType(node);
point = toNode(obj);
CIntrusiveTreeBase::insert(point, parent);
return obj;
}
void remove(T* obj)
{
CIntrusiveTreeBase::remove(toNode(obj));
}
};

View File

@@ -0,0 +1,120 @@
/*
** Sample Framework for deko3d Applications
** CMemPool.h: Pooled dynamic memory allocation manager class
*/
#pragma once
#include "common.h"
#include "CIntrusiveList.h"
#include "CIntrusiveTree.h"
class CMemPool
{
dk::Device m_dev;
uint32_t m_flags;
uint32_t m_blockSize;
struct Block
{
CIntrusiveListNode<Block> m_node;
dk::MemBlock m_obj;
void* m_cpuAddr;
DkGpuAddr m_gpuAddr;
constexpr void* cpuOffset(uint32_t offset) const
{
return m_cpuAddr ? ((u8*)m_cpuAddr + offset) : nullptr;
}
constexpr DkGpuAddr gpuOffset(uint32_t offset) const
{
return m_gpuAddr != DK_GPU_ADDR_INVALID ? (m_gpuAddr + offset) : DK_GPU_ADDR_INVALID;
}
};
CIntrusiveList<Block, &Block::m_node> m_blocks;
struct Slice
{
CIntrusiveListNode<Slice> m_node;
CIntrusiveTreeNode m_treenode;
CMemPool* m_pool;
Block* m_block;
uint32_t m_start;
uint32_t m_end;
constexpr uint32_t getSize() const { return m_end - m_start; }
constexpr bool canCoalesce(Slice const& rhs) const { return m_pool == rhs.m_pool && m_block == rhs.m_block && m_end == rhs.m_start; }
constexpr bool operator<(Slice const& rhs) const { return getSize() < rhs.getSize(); }
constexpr bool operator<(uint32_t rhs) const { return getSize() < rhs; }
};
friend constexpr bool operator<(uint32_t lhs, Slice const& rhs);
CIntrusiveList<Slice, &Slice::m_node> m_memMap, m_sliceHeap;
CIntrusiveTree<Slice, &Slice::m_treenode> m_freeList;
Slice* _newSlice();
void _deleteSlice(Slice*);
void _destroy(Slice* slice);
public:
static constexpr uint32_t DefaultBlockSize = 0x800000;
class Handle
{
Slice* m_slice;
public:
constexpr Handle(Slice* slice = nullptr) : m_slice{slice} { }
constexpr operator bool() const { return m_slice != nullptr; }
constexpr operator Slice*() const { return m_slice; }
constexpr bool operator!() const { return !m_slice; }
constexpr bool operator==(Handle const& rhs) const { return m_slice == rhs.m_slice; }
constexpr bool operator!=(Handle const& rhs) const { return m_slice != rhs.m_slice; }
void destroy()
{
if (m_slice)
{
m_slice->m_pool->_destroy(m_slice);
m_slice = nullptr;
}
}
constexpr dk::MemBlock getMemBlock() const
{
return m_slice->m_block->m_obj;
}
constexpr uint32_t getOffset() const
{
return m_slice->m_start;
}
constexpr uint32_t getSize() const
{
return m_slice->getSize();
}
constexpr void* getCpuAddr() const
{
return m_slice->m_block->cpuOffset(m_slice->m_start);
}
constexpr DkGpuAddr getGpuAddr() const
{
return m_slice->m_block->gpuOffset(m_slice->m_start);
}
};
CMemPool(dk::Device dev, uint32_t flags = DkMemBlockFlags_CpuUncached | DkMemBlockFlags_GpuCached, uint32_t blockSize = DefaultBlockSize) :
m_dev{dev}, m_flags{flags}, m_blockSize{blockSize}, m_blocks{}, m_memMap{}, m_sliceHeap{}, m_freeList{} { }
~CMemPool();
Handle allocate(uint32_t size, uint32_t alignment = DK_CMDMEM_ALIGNMENT);
};
constexpr bool operator<(uint32_t lhs, CMemPool::Slice const& rhs)
{
return lhs < rhs.getSize();
}

View File

@@ -0,0 +1,31 @@
/*
** Sample Framework for deko3d Applications
** CShader.h: Utility class for loading shaders from the filesystem
*/
#pragma once
#include "common.h"
#include "CMemPool.h"
class CShader
{
dk::Shader m_shader;
CMemPool::Handle m_codemem;
public:
CShader() : m_shader{}, m_codemem{} { }
~CShader()
{
m_codemem.destroy();
}
constexpr operator bool() const
{
return m_codemem;
}
constexpr operator dk::Shader const*() const
{
return &m_shader;
}
bool load(CMemPool& pool, const char* path);
};

View File

@@ -0,0 +1,9 @@
/*
** Sample Framework for deko3d Applications
** FileLoader.h: Helpers for loading data from the filesystem directly into GPU memory
*/
#pragma once
#include "common.h"
#include "CMemPool.h"
CMemPool::Handle LoadFile(CMemPool& pool, const char* path, uint32_t alignment = DK_CMDMEM_ALIGNMENT);

View File

@@ -0,0 +1,12 @@
/*
** Sample Framework for deko3d Applications
** common.h: Common includes
*/
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <switch.h>
#include <deko3d.hpp>

View File

@@ -0,0 +1,158 @@
//
// Copyright (c) 2009-2013 Mikko Mononen memon@inside.org
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would be
// appreciated but is not required.
// 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source distribution.
//
#ifndef NANOVG_GL_UTILS_H
#define NANOVG_GL_UTILS_H
#ifdef USE_OPENGL
struct NVGLUframebuffer {
NVGcontext* ctx;
GLuint fbo;
GLuint rbo;
GLuint texture;
int image;
};
typedef struct NVGLUframebuffer NVGLUframebuffer;
// Helper function to create GL frame buffer to render to.
void nvgluBindFramebuffer(NVGLUframebuffer* fb);
NVGLUframebuffer* nvgluCreateFramebuffer(NVGcontext* ctx, int w, int h, int imageFlags);
void nvgluDeleteFramebuffer(NVGLUframebuffer* fb);
#endif // NANOVG_GL_UTILS_H
#ifdef NANOVG_GL_IMPLEMENTATION
#if defined(NANOVG_GL3) || defined(NANOVG_GLES2) || defined(NANOVG_GLES3)
// FBO is core in OpenGL 3>.
# define NANOVG_FBO_VALID 1
#elif defined(NANOVG_GL2)
// On OS X including glext defines FBO on GL2 too.
# ifdef __APPLE__
# include <OpenGL/glext.h>
# define NANOVG_FBO_VALID 1
# endif
#endif
static GLint defaultFBO = -1;
NVGLUframebuffer* nvgluCreateFramebuffer(NVGcontext* ctx, int w, int h, int imageFlags)
{
#ifdef NANOVG_FBO_VALID
GLint defaultFBO;
GLint defaultRBO;
NVGLUframebuffer* fb = NULL;
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &defaultFBO);
glGetIntegerv(GL_RENDERBUFFER_BINDING, &defaultRBO);
fb = (NVGLUframebuffer*)malloc(sizeof(NVGLUframebuffer));
if (fb == NULL) goto error;
memset(fb, 0, sizeof(NVGLUframebuffer));
fb->image = nvgCreateImageRGBA(ctx, w, h, imageFlags | NVG_IMAGE_FLIPY | NVG_IMAGE_PREMULTIPLIED, NULL);
#if defined NANOVG_GL2
fb->texture = nvglImageHandleGL2(ctx, fb->image);
#elif defined NANOVG_GL3
fb->texture = nvglImageHandleGL3(ctx, fb->image);
#elif defined NANOVG_GLES2
fb->texture = nvglImageHandleGLES2(ctx, fb->image);
#elif defined NANOVG_GLES3
fb->texture = nvglImageHandleGLES3(ctx, fb->image);
#endif
fb->ctx = ctx;
// frame buffer object
glGenFramebuffers(1, &fb->fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fb->fbo);
// render buffer object
glGenRenderbuffers(1, &fb->rbo);
glBindRenderbuffer(GL_RENDERBUFFER, fb->rbo);
glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, w, h);
// combine all
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fb->texture, 0);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fb->rbo);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
#ifdef GL_DEPTH24_STENCIL8
// If GL_STENCIL_INDEX8 is not supported, try GL_DEPTH24_STENCIL8 as a fallback.
// Some graphics cards require a depth buffer along with a stencil.
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, w, h);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fb->texture, 0);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fb->rbo);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
#endif // GL_DEPTH24_STENCIL8
goto error;
}
glBindFramebuffer(GL_FRAMEBUFFER, defaultFBO);
glBindRenderbuffer(GL_RENDERBUFFER, defaultRBO);
return fb;
error:
glBindFramebuffer(GL_FRAMEBUFFER, defaultFBO);
glBindRenderbuffer(GL_RENDERBUFFER, defaultRBO);
nvgluDeleteFramebuffer(fb);
return NULL;
#else
NVG_NOTUSED(ctx);
NVG_NOTUSED(w);
NVG_NOTUSED(h);
NVG_NOTUSED(imageFlags);
return NULL;
#endif
}
void nvgluBindFramebuffer(NVGLUframebuffer* fb)
{
#ifdef NANOVG_FBO_VALID
if (defaultFBO == -1) glGetIntegerv(GL_FRAMEBUFFER_BINDING, &defaultFBO);
glBindFramebuffer(GL_FRAMEBUFFER, fb != NULL ? fb->fbo : defaultFBO);
#else
NVG_NOTUSED(fb);
#endif
}
void nvgluDeleteFramebuffer(NVGLUframebuffer* fb)
{
#ifdef NANOVG_FBO_VALID
if (fb == NULL) return;
if (fb->fbo != 0)
glDeleteFramebuffers(1, &fb->fbo);
if (fb->rbo != 0)
glDeleteRenderbuffers(1, &fb->rbo);
if (fb->image >= 0)
nvgDeleteImage(fb->ctx, fb->image);
fb->ctx = NULL;
fb->fbo = 0;
fb->rbo = 0;
fb->texture = 0;
fb->image = -1;
free(fb);
#else
NVG_NOTUSED(fb);
#endif
}
#endif
#endif // NANOVG_GL_IMPLEMENTATION

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff