]> Chaos Git - corbenik/ctrulib.git/commitdiff
Add a VRAM allocator
authorfincs <fincs.alt1@gmail.com>
Sun, 14 Dec 2014 16:47:34 +0000 (17:47 +0100)
committerfincs <fincs.alt1@gmail.com>
Sun, 14 Dec 2014 16:47:34 +0000 (17:47 +0100)
libctru/include/3ds.h
libctru/include/3ds/vram.h [new file with mode: 0644]
libctru/source/allocator/addrmap.h [new file with mode: 0644]
libctru/source/allocator/linear.cpp
libctru/source/allocator/vram.cpp [new file with mode: 0644]

index d128d25d62506cb51b8bf2b2750e72ec7fb4a539..73734069b5395b247f0a1cb7b281777c8ae1a765 100644 (file)
@@ -9,6 +9,7 @@ extern "C" {
 #include <3ds/svc.h>
 #include <3ds/srv.h>
 #include <3ds/linear.h>
+#include <3ds/vram.h>
 #include <3ds/os.h>
 #include <3ds/gfx.h>
 #include <3ds/console.h>
diff --git a/libctru/include/3ds/vram.h b/libctru/include/3ds/vram.h
new file mode 100644 (file)
index 0000000..9743410
--- /dev/null
@@ -0,0 +1,8 @@
+#pragma once
+
+// Functions for allocating/deallocating VRAM
+void* vramAlloc(size_t size); // returns a 16-byte aligned address
+void* vramMemAlign(size_t size, size_t alignment);
+void* vramRealloc(void* mem, size_t size); // not implemented yet
+void vramFree(void* mem);
+u32 vramSpaceFree(); // get free VRAM space in bytes
diff --git a/libctru/source/allocator/addrmap.h b/libctru/source/allocator/addrmap.h
new file mode 100644 (file)
index 0000000..11e8183
--- /dev/null
@@ -0,0 +1,48 @@
+#pragma once
+
+static rbtree_t sAddrMap;
+
+struct addrMapNode
+{
+       rbtree_node node;
+       MemChunk chunk;
+};
+
+#define getAddrMapNode(x) rbtree_item((x), addrMapNode, node)
+
+static int addrMapNodeComparator(const rbtree_node_t* _lhs, const rbtree_node_t* _rhs)
+{
+       auto lhs = getAddrMapNode(_lhs)->chunk.addr;
+       auto rhs = getAddrMapNode(_rhs)->chunk.addr;
+       if (lhs < rhs)
+               return -1;
+       if (lhs > rhs)
+               return 1;
+       return 0;
+}
+
+static void addrMapNodeDestructor(rbtree_node_t* a)
+{
+       free(getAddrMapNode(a));
+}
+
+static addrMapNode* getNode(void* addr)
+{
+       addrMapNode n;
+       n.chunk.addr = (u8*)addr;
+       auto p = rbtree_find(&sAddrMap, &n.node);
+       return p ? getAddrMapNode(p) : nullptr;
+}
+
+static addrMapNode* newNode(const MemChunk& chunk)
+{
+       auto p = (addrMapNode*)malloc(sizeof(addrMapNode));
+       if (!p) return nullptr;
+       p->chunk = chunk;
+       return p;
+}
+
+static void delNode(addrMapNode* node)
+{
+       rbtree_remove(&sAddrMap, &node->node, addrMapNodeDestructor);
+}
index 0d7819b52f76412a5342da565d6588111f424007..0ad052cd919c48aea1eb50ab0e34c15e039d71a3 100644 (file)
@@ -6,56 +6,11 @@ extern "C"
 }
 
 #include "mem_pool.h"
+#include "addrmap.h"
 
 extern u32 __linear_heap, __linear_heap_size;
 
 static MemPool sLinearPool;
-static rbtree_t sAddrMap;
-
-struct addrMapNode
-{
-       rbtree_node node;
-       MemChunk chunk;
-};
-
-#define getAddrMapNode(x) rbtree_item((x), addrMapNode, node)
-
-static int addrMapNodeComparator(const rbtree_node_t* _lhs, const rbtree_node_t* _rhs)
-{
-       auto lhs = getAddrMapNode(_lhs)->chunk.addr;
-       auto rhs = getAddrMapNode(_rhs)->chunk.addr;
-       if (lhs < rhs)
-               return -1;
-       if (lhs > rhs)
-               return 1;
-       return 0;
-}
-
-static void addrMapNodeDestructor(rbtree_node_t* a)
-{
-       free(getAddrMapNode(a));
-}
-
-static addrMapNode* getNode(void* addr)
-{
-       addrMapNode n;
-       n.chunk.addr = (u8*)addr;
-       auto p = rbtree_find(&sAddrMap, &n.node);
-       return p ? getAddrMapNode(p) : nullptr;
-}
-
-static addrMapNode* newNode(const MemChunk& chunk)
-{
-       auto p = (addrMapNode*)malloc(sizeof(addrMapNode));
-       if (!p) return nullptr;
-       p->chunk = chunk;
-       return p;
-}
-
-static void delNode(addrMapNode* node)
-{
-       rbtree_remove(&sAddrMap, &node->node, addrMapNodeDestructor);
-}
 
 static bool linearInit()
 {
diff --git a/libctru/source/allocator/vram.cpp b/libctru/source/allocator/vram.cpp
new file mode 100644 (file)
index 0000000..4918729
--- /dev/null
@@ -0,0 +1,86 @@
+extern "C"
+{
+       #include <3ds/types.h>
+       #include <3ds/vram.h>
+       #include <3ds/util/rbtree.h>
+}
+
+#include "mem_pool.h"
+#include "addrmap.h"
+
+static MemPool sVramPool;
+
+static bool vramInit()
+{
+       auto blk = MemBlock::Create((u8*)0x1F000000, 0x00600000);
+       if (blk)
+       {
+               sVramPool.AddBlock(blk);
+               rbtree_init(&sAddrMap, addrMapNodeComparator);
+               return true;
+       }
+       return false;
+}
+
+void* vramMemAlign(size_t size, size_t alignment)
+{
+       // Enforce minimum alignment
+       if (alignment < 16)
+               alignment = 16;
+
+       // Convert alignment to shift amount
+       int shift;
+       for (shift = 4; shift < 32; shift ++)
+       {
+               if ((1U<<shift) == alignment)
+                       break;
+       }
+       if (shift == 32) // Invalid alignment
+               return nullptr;
+
+       // Initialize the pool if it is not ready
+       if (!sVramPool.Ready() && !vramInit())
+               return nullptr;
+
+       // Allocate the chunk
+       MemChunk chunk;
+       if (!sVramPool.Allocate(chunk, size, shift))
+               return nullptr;
+
+       auto node = newNode(chunk);
+       if (!node)
+       {
+               sVramPool.Deallocate(chunk);
+               return nullptr;
+       }
+       if (rbtree_insert(&sAddrMap, &node->node));
+       return chunk.addr;
+}
+
+void* vramAlloc(size_t size)
+{
+       return vramMemAlign(size, 16);
+}
+
+void* vramRealloc(void* mem, size_t size)
+{
+       // TODO
+       return NULL;
+}
+
+void vramFree(void* mem)
+{
+       auto node = getNode(mem);
+       if (!node) return;
+
+       // Free the chunk
+       sVramPool.Deallocate(node->chunk);
+
+       // Free the node
+       delNode(node);
+}
+
+u32 vramSpaceFree()
+{
+       return sVramPool.GetFreeSpace();
+}