sdk-world v2026.11.05
PS2 SDK - world tier (copyleft-allowed, non-essential packages)
Loading...
Searching...
No Matches
gsTexManager.c
1// ____ ___ | / _____ _____
2// | __ | |___/ | |
3// |___| ___| | \ __|__ | gsKit Open Source Project.
4// ----------------------------------------------------------------------
5// Copyright 2017 - Rick "Maximus32" Gaiser <rgaiser@gmail.com>
6// Copyright 2004 - Chris "Neovanglist" Gilbert <Neovanglist@LainOS.org>
7// Licenced under Academic Free License version 2.0
8// Review gsKit README & LICENSE files for further details.
9//
10// gsHires.c - Multi pass high resolution rendering
11//
12
13#include <stdio.h>
14#include <malloc.h>
15#include <kernel.h>
16#include "gsTexManager.h"
17
18
19struct SVramBlock {
20 unsigned int iStart;
21 unsigned int iSize;
22 unsigned int iUseCount;
23 unsigned int iUseCountPrev;
24
25 GSTEXTURE * tex;
26 struct SVramBlock * pNext;
27 struct SVramBlock * pPrev;
28};
29struct SVramBlock * __head = NULL;
30enum ETransferMode __trmode = ETM_INLINE;
31
32
33//---------------------------------------------------------------------------
34// Private functions
35
36//---------------------------------------------------------------------------
37static inline struct SVramBlock *
38_blockCreate(unsigned int start, unsigned int size)
39{
40 struct SVramBlock * block;
41
42 block = malloc(sizeof(struct SVramBlock));
43
44 block->iStart = start;
45 block->iSize = size;
46 block->iUseCount = 0;
47 block->iUseCountPrev = 0;
48
49 block->tex = NULL;
50 block->pNext = NULL;
51 block->pPrev = NULL;
52
53 return block;
54}
55
56//---------------------------------------------------------------------------
57static inline void
58_blockInsertAfter(struct SVramBlock * block, struct SVramBlock * next)
59{
60 next->pNext = block->pNext;
61 next->pPrev = block;
62 if(block->pNext != NULL)
63 block->pNext->pPrev = next;
64 block->pNext = next;
65}
66
67//---------------------------------------------------------------------------
68static inline struct SVramBlock *
69_blockRemove(struct SVramBlock * block)
70{
71 struct SVramBlock * next = block->pNext;
72
73 if(block->pPrev != NULL)
74 block->pPrev->pNext = block->pNext;
75 if(block->pNext != NULL)
76 block->pNext->pPrev = block->pPrev;
77
78 free(block);
79
80 return next;
81}
82
83//---------------------------------------------------------------------------
84static inline struct SVramBlock *
85_blockSplitFree(struct SVramBlock * block, unsigned int size)
86{
87 struct SVramBlock * pNewBlock;
88
89 // Create second block with leftover size
90 pNewBlock = _blockCreate(block->iStart + size, block->iSize - size);
91 // Shrink first block
92 block->iSize = size;
93 // Insert second block after first block
94 _blockInsertAfter(block, pNewBlock);
95
96 return block;
97}
98
99//---------------------------------------------------------------------------
100static inline struct SVramBlock *
101_blockMergeFree(struct SVramBlock * block)
102{
103 // Search backwards to the first free block
104 while ((block->pPrev != NULL) && (block->pPrev->tex == NULL))
105 block = block->pPrev;
106
107 // Merge free blocks
108 while((block->pNext != NULL) && (block->pNext->tex == NULL)) {
109 block->iSize += block->pNext->iSize;
110 _blockRemove(block->pNext);
111 }
112
113 return block;
114}
115
116//---------------------------------------------------------------------------
117// How often is this vram block used, mainly based on predictions
118static inline unsigned int
119_blockGetWeight(struct SVramBlock * block)
120{
121 unsigned int weight = 0;
122
123 if ((block != NULL) && (block->tex != NULL)) {
124 if(block->iUseCount == block->iUseCountPrev) {
125 // Prediction:
126 // - This frame: done
127 // - Next frame: needed
128 weight += block->iUseCountPrev;
129 }
130 else if(block->iUseCount < block->iUseCountPrev) {
131 // Prediction:
132 // - This frame: needed
133 weight += block->iUseCountPrev - block->iUseCount;
134 // - Next frame: needed
135 weight += block->iUseCountPrev;
136 }
137 else {
138 // Prediction:
139 // - This frame: unsure
140 weight += 1;
141 // - Next frame: needed
142 weight += block->iUseCount;
143 }
144 }
145
146 return weight;
147}
148
149//---------------------------------------------------------------------------
150// Simple block allocator
151static inline struct SVramBlock *
152_blockAlloc(unsigned int size)
153{
154 struct SVramBlock * block = NULL;
155 unsigned int weight = 0;
156
157 // Locate free block
158 for (block = __head; block != NULL; block = block->pNext) {
159 if ((block->tex == NULL) && (block->iSize >= size)) {
160 // Free block found (first fit)
161 break;
162 }
163 }
164
165 while (block == NULL) {
166 // Free blocks starting with the least used textures
167 for (block = __head; block != NULL; block = block->pNext) {
168 if ((block->tex != NULL) && (_blockGetWeight(block) <= weight)) {
169 // Free block
170 block->tex = NULL;
171 block = _blockMergeFree(block);
172 if (block->iSize >= size) {
173 // Free block found (created)
174 break;
175 }
176 }
177 }
178 weight++;
179 }
180
181 // Split the block into the right size
182 if (block != NULL) {
183 block = _blockSplitFree(block, size);
184 }
185
186 return block;
187}
188
189//---------------------------------------------------------------------------
190// Public functions
191
192//---------------------------------------------------------------------------
193void
195{
196 struct SVramBlock * block = __head;
197
198 // Delete all blocks (if present)
199 while(block != NULL)
200 block = _blockRemove(block);
201
202 // Allocate the initial free block
203 __head = _blockCreate(gsGlobal->CurrentPointer, (4*1024*1024) - gsGlobal->CurrentPointer);
204}
205
206//---------------------------------------------------------------------------
207void
208gsKit_TexManager_setmode(GSGLOBAL * gsGlobal, enum ETransferMode mode)
209{
210 __trmode = mode;
211}
212
213//---------------------------------------------------------------------------
214unsigned int
215gsKit_TexManager_bind(GSGLOBAL * gsGlobal, GSTEXTURE * tex)
216{
217 struct SVramBlock * block;
218 unsigned int ttransfer = 0;
219 unsigned int ctransfer = 0;
220 unsigned int tsize;
221 unsigned int csize = 0;
222 unsigned int cwidth = 16;
223 unsigned int cheight = 16;
224
225 // Locate texture
226 for (block = __head; block != NULL; block = block->pNext) {
227 if(block->tex == tex)
228 break;
229 }
230
231 tsize = gsKit_texture_size(tex->Width, tex->Height, tex->PSM);
232 if (tex->Clut != NULL) {
233 cwidth = (tex->PSM == GS_PSM_T8) ? 16 : 8;
234 cheight = (tex->PSM == GS_PSM_T8) ? 16 : 2;
235 csize = gsKit_texture_size(cwidth, cheight, tex->ClutPSM);
236 }
237
238 // Allocate new block if not already loaded
239 if (block == NULL) {
240 block = _blockAlloc(tsize + csize);
241 block->tex = tex;
242 block->iUseCount = 0;
243 block->iUseCountPrev = 1;
244
245 tex->Vram = 0;
246 tex->VramClut = 0;
247 }
248
249 // (Re-)transfer texture if invalidated
250 if (tex->Vram == 0)
251 ttransfer = 1;
252
253 // (Re-)transfer clut if invalidated
254 if ((tex->Clut) && (tex->VramClut == 0))
255 ctransfer = 1;
256
257 if (ttransfer) {
258 tex->Vram = block->iStart;
259 gsKit_setup_tbw(tex);
260 SyncDCache(tex->Mem, (u8 *)(tex->Mem) + tsize);
261 if (__trmode == ETM_INLINE)
262 gsKit_texture_send_inline(gsGlobal, tex->Mem, tex->Width, tex->Height, tex->Vram, tex->PSM, tex->TBW, tex->Clut ? GS_CLUT_TEXTURE : GS_CLUT_NONE);
263 else
264 gsKit_texture_send(tex->Mem, tex->Width, tex->Height, tex->Vram, tex->PSM, tex->TBW, tex->Clut ? GS_CLUT_TEXTURE : GS_CLUT_NONE);
265 }
266
267 if (ctransfer) {
268 tex->VramClut = block->iStart + tsize;
269 SyncDCache(tex->Clut, (u8 *)(tex->Clut) + csize);
270 if (__trmode == ETM_INLINE)
271 gsKit_texture_send_inline(gsGlobal, tex->Clut, cwidth, cheight, tex->VramClut, tex->ClutPSM, 1, GS_CLUT_PALLETE);
272 else
273 gsKit_texture_send(tex->Clut, cwidth, cheight, tex->VramClut, tex->ClutPSM, 1, GS_CLUT_PALLETE);
274 }
275
276 block->iUseCount++;
277
278 return (ttransfer|ctransfer);
279}
280
281//---------------------------------------------------------------------------
282void
283gsKit_TexManager_invalidate(GSGLOBAL * gsGlobal, GSTEXTURE * tex)
284{
285 tex->Vram = 0;
286 tex->VramClut = 0;
287}
288
289//---------------------------------------------------------------------------
290void
291gsKit_TexManager_free(GSGLOBAL * gsGlobal, GSTEXTURE * tex)
292{
293 struct SVramBlock * block;
294
295 // Locate texture
296 for (block = __head; block != NULL; block = block->pNext) {
297 if(block->tex == tex) {
298 // Free block
299 block->tex = NULL;
300 _blockMergeFree(block);
301 tex->Vram = 0;
302 tex->VramClut = 0;
303 break;
304 }
305 }
306}
307
308//---------------------------------------------------------------------------
309void
311{
312 struct SVramBlock * block;
313
314 // Register use count
315 for(block = __head; block != NULL; block = block->pNext) {
316 if(block->tex != NULL) {
317 block->iUseCountPrev = block->iUseCount;
318 block->iUseCount = 0;
319 }
320 }
321}
#define GS_PSM_T8
8 Bit Texture with CLUT
Definition gsInit.h:123
void gsKit_TexManager_init(GSGLOBAL *gsGlobal)
Initialize the texture manager.
unsigned int gsKit_TexManager_bind(GSGLOBAL *gsGlobal, GSTEXTURE *tex)
Bind a texture to VRAM, will automatically transfer the texture.
void gsKit_TexManager_nextFrame(GSGLOBAL *gsGlobal)
void gsKit_TexManager_setmode(GSGLOBAL *gsGlobal, enum ETransferMode mode)
Set the texture transfer mode (inline or direct).
void gsKit_TexManager_invalidate(GSGLOBAL *gsGlobal, GSTEXTURE *tex)
Invalidate a texture, will automatically transfer the texture on next bind call.
void gsKit_TexManager_free(GSGLOBAL *gsGlobal, GSTEXTURE *tex)
u32 CurrentPointer
Current VRAM Pointer.
Definition gsInit.h:904
u32 * Clut
EE CLUT Memory Pointer.
Definition gsInit.h:962
u32 TBW
Texture Base Width.
Definition gsInit.h:960
u32 * Mem
EE Memory Pointer.
Definition gsInit.h:961
u32 Vram
GS VRAM Memory Pointer.
Definition gsInit.h:963
u32 VramClut
GS VRAM CLUT Memory Pointer.
Definition gsInit.h:964
u8 ClutPSM
CLUT Pixel Storage Method (Color Format).
Definition gsInit.h:959
u8 PSM
Pixel Storage Method (Color Format).
Definition gsInit.h:958
u32 Height
Height of the Texture.
Definition gsInit.h:957
u32 Width
Width of the Texture.
Definition gsInit.h:956