1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     demo_GraphicsMemoryAllocator.cpp
4 
5   Copyright (C)2009-2011 Nintendo/HAL Laboratory, Inc.  All rights reserved.
6 
7   These coded instructions, statements, and computer programs contain proprietary
8   information of Nintendo and/or its licensed developers and are protected by
9   national and international copyright laws. They may not be disclosed to third
10   parties or copied or duplicated in any form, in whole or in part, without the
11   prior written consent of Nintendo.
12 
13   The content herein is highly confidential and should be handled accordingly.
14 
15   $Revision: 31311 $
16  *---------------------------------------------------------------------------*/
17 
18 #include <nw/ut/ut_Preprocessor.h>
19 #include <nw/demo/demo_GraphicsMemoryAllocator.h>
20 #include <nn.h>
21 #include <nn/gx.h>
22 
23 namespace nw
24 {
25 namespace demo
26 {
27 
28 const int ALIGNMENT_SYSTEM_BUFFER     = 4;
29 const int ALIGNMENT_VERTEX            = 4;
30 const int ALIGNMENT_TEXTURE           = 128;
31 const int ALIGNMENT_RENDER_BUFFER     = 64;    // 24ビットフォーマット(RGB8,D24)のバッファは96Byteアラインが必要
32 const int ALIGNMENT_DISPLAY_BUFFER    = 16;
33 const int ALIGNMENT_3D_COMMAND_BUFFER = 16;
34 
35 //--------------------------------------------------------------------------
36 void
Initialize(os::IAllocator * allocator)37 GraphicsMemoryAllocator::Initialize(os::IAllocator* allocator)
38 {
39     m_CurrentAddrVramA = nn::gx::GetVramStartAddr(nn::gx::MEM_VRAMA);
40     m_CurrentAddrVramB = nn::gx::GetVramStartAddr(nn::gx::MEM_VRAMB);
41 
42     m_DeviceMemoryAllocator = allocator;
43 
44     m_Initialized = true;
45 }
46 
47 //--------------------------------------------------------------------------
48 void
Finalize(void)49 GraphicsMemoryAllocator::Finalize(void)
50 {
51     m_CurrentAddrVramA = nn::gx::GetVramStartAddr(nn::gx::MEM_VRAMA);
52     m_CurrentAddrVramB = nn::gx::GetVramStartAddr(nn::gx::MEM_VRAMB);
53 }
54 
55 //--------------------------------------------------------------------------
56 void*
Allocate(GLenum area,GLenum aim,GLuint id,GLsizei size)57 GraphicsMemoryAllocator::Allocate(GLenum area, GLenum aim, GLuint id, GLsizei size)
58 {
59     NW_UNUSED_VARIABLE(id);
60 
61     NW_ASSERTMSG (m_Initialized, "[DEMO:GraphicsMemoryAllocator] not initialized.\n");
62 
63     if (size == 0) { return 0; }
64 
65     // 現在のところ、VRAM-A or VRAM-B にCTR のシステムのための予約領域がどの程度置かれるのか不明
66 
67     // VRAM にアロケートする場合は、簡単のために VRAM をスタックのように扱う
68     // さらに、断片化には対処しない
69     // 断片化に対処するには、確保成功時に area, aim, id といった確保したメモリに対する情報を
70     // のちのデアロケートのために保持しておく必要があるはず
71 
72     int addrAlign = 8;
73     void* resultAddr = NULL;
74 
75     // 各データの配置に対するアラインメントの制約を考慮
76     switch (aim)
77     {
78     case NN_GX_MEM_SYSTEM:
79         addrAlign = ALIGNMENT_SYSTEM_BUFFER;
80         break;
81     case NN_GX_MEM_TEXTURE:
82         addrAlign = ALIGNMENT_TEXTURE;
83         break;
84     case NN_GX_MEM_VERTEXBUFFER:
85         addrAlign = ALIGNMENT_VERTEX;
86         break;
87     case NN_GX_MEM_RENDERBUFFER:
88         addrAlign = ALIGNMENT_RENDER_BUFFER;
89         break;
90     case NN_GX_MEM_DISPLAYBUFFER:
91         addrAlign = ALIGNMENT_DISPLAY_BUFFER;
92         break;
93     case NN_GX_MEM_COMMANDBUFFER:
94         addrAlign = ALIGNMENT_3D_COMMAND_BUFFER;
95         break;
96     default:
97         NW_FATAL_ERROR("[DEMO:GraphicsMemoryAllocator] invalid parameter.(0x%X)\n", aim);
98         break;
99     }
100 
101 
102     switch (area)
103     {
104     case NN_GX_MEM_FCRAM:
105         // FCRAM の場合は SDK サポートの拡張ヒープから割り当てるため管理しない
106         resultAddr = m_DeviceMemoryAllocator->Alloc(size, addrAlign);
107         break;
108     case NN_GX_MEM_VRAMA:
109         {
110             if (MathRoundup(m_CurrentAddrVramA, addrAlign) + size > nn::gx::GetVramEndAddr(nn::gx::MEM_VRAMA))
111             {
112                 NW_FATAL_ERROR("[DEMO:GraphicsMemoryAllocator] lack of resource on VRAM-A.\n");
113             }
114             m_CurrentAddrVramA = MathRoundup(m_CurrentAddrVramA, addrAlign);
115             resultAddr = reinterpret_cast<void*>(m_CurrentAddrVramA);
116             m_CurrentAddrVramA += size;
117         }
118         break;
119     case NN_GX_MEM_VRAMB:
120         {
121             if (MathRoundup(m_CurrentAddrVramB, addrAlign) + size > nn::gx::GetVramEndAddr(nn::gx::MEM_VRAMB))
122             {
123                 NW_FATAL_ERROR("[DEMO:GraphicsMemoryAllocator] lack of resource on VRAM-B.\n");
124             }
125             m_CurrentAddrVramB = MathRoundup(m_CurrentAddrVramB, addrAlign);
126             resultAddr = reinterpret_cast<void*>(m_CurrentAddrVramB);
127             m_CurrentAddrVramB += size;
128         }
129         break;
130     default:
131         // 通常の使用ではまずありえないため FATAL_ERROR
132         NW_FATAL_ERROR("[DEMO:GraphicsMemoryAllocator] invalid parameter.(0x%X)\n", area);
133         break;
134     }
135 
136     NW_NULL_ASSERT(resultAddr);
137 
138     return resultAddr;
139 }
140 
141 //--------------------------------------------------------------------------
142 void
Deallocate(GLenum area,GLenum aim,GLuint id,void * addr)143 GraphicsMemoryAllocator::Deallocate(GLenum area, GLenum aim, GLuint id, void* addr)
144 {
145     NW_ASSERTMSG (m_Initialized, "[DEMO:GraphicsMemoryAllocator] not initialized.\n");
146     NW_UNUSED_VARIABLE(aim);
147     NW_UNUSED_VARIABLE(id);
148 
149     switch (area)
150     {
151     case NN_GX_MEM_FCRAM:
152         m_DeviceMemoryAllocator->Free(addr);
153         break;
154 
155     default:
156         // TODO: グラフィックスメモリアロケーターのデアロケータを実装する
157         break;
158     }
159 }
160 
161 
162 } // namespace demo
163 } // namespace nw
164