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