3 Licenced under Academic Free License version 3.0
4 Review OpenUsbLd README & LICENSE files for further details.
8 #include "include/atlas.h"
10 static inline struct atlas_allocation_t
*allocNew(int x
, int y
, size_t width
, size_t height
) {
11 struct atlas_allocation_t
*al
= (struct atlas_allocation_t
*)malloc(sizeof(struct atlas_allocation_t
));
24 static inline void allocFree(struct atlas_allocation_t
*alloc
) {
28 // NOTE: If used on a tree component it
29 // would have to be ensured pointers to freed
30 // allocation are fixed
32 allocFree(alloc
->leaf1
); // safe
33 allocFree(alloc
->leaf2
);
38 #define ALLOC_FITS(alloc,width,height) \
39 ((alloc->w >= width) && (alloc->h >= height))
41 #define ALLOC_ISFREE(alloc) \
42 ((!alloc->leaf1) && (!alloc->leaf2))
45 static inline struct atlas_allocation_t
*allocPlace(struct atlas_allocation_t
*alloc
, size_t width
, size_t height
) {
47 if (!ALLOC_FITS(alloc
, width
, height
))
50 if (ALLOC_ISFREE(alloc
)) {
52 size_t dx
= alloc
->w
- width
;
53 size_t dy
= alloc
->h
- height
;
55 // make the wider piece also longer - less wasted space
57 alloc
->leaf1
= allocNew(alloc
->x
+ width
, alloc
->y
, dx
, height
);
58 alloc
->leaf2
= allocNew(alloc
->x
, alloc
->y
+ height
, alloc
->w
, dy
);
60 alloc
->leaf1
= allocNew(alloc
->x
, alloc
->y
+ height
, width
, dy
);
61 alloc
->leaf2
= allocNew(alloc
->x
+ width
, alloc
->y
, dx
, alloc
->h
);
66 // already occupied. Try children
67 struct atlas_allocation_t
* p
= allocPlace(alloc
->leaf1
, width
, height
);
71 p
= allocPlace(alloc
->leaf2
, width
, height
);
79 atlas_t
*atlasNew(size_t width
, size_t height
, u8 psm
) {
80 atlas_t
*atlas
= (atlas_t
*)malloc(sizeof(atlas_t
));
82 atlas
->allocation
= allocNew(0, 0, width
, height
);
84 atlas
->surface
.Width
= width
;
85 atlas
->surface
.Height
= height
;
87 atlas
->surface
.Filter
= GS_FILTER_LINEAR
;
89 size_t txtsize
= gsKit_texture_size(width
, height
, psm
);
90 atlas
->surface
.PSM
= psm
;
91 atlas
->surface
.Mem
= (u32
*) memalign(128, txtsize
);
92 atlas
->surface
.Vram
= 0;
94 // defaults to no clut
95 atlas
->surface
.ClutPSM
= 0;
96 atlas
->surface
.Clut
= NULL
;
97 atlas
->surface
.VramClut
= 0;
99 // zero out the atlas surface
100 memset(atlas
->surface
.Mem
, 0x0, txtsize
);
105 void atlasFree(atlas_t
*atlas
) {
109 allocFree(atlas
->allocation
);
110 atlas
->allocation
= NULL
;
112 free(atlas
->surface
.Mem
);
113 atlas
->surface
.Mem
= NULL
;
118 static size_t pixelSize(u8 psm
) {
120 case GS_PSM_CT32
: return 4;
121 case GS_PSM_CT24
: return 4;
122 case GS_PSM_CT16
: return 2;
123 case GS_PSM_CT16S
: return 2;
124 case GS_PSM_T8
: return 1;
130 // copies the data into atlas
131 static void atlasCopyData(atlas_t
*atlas
, struct atlas_allocation_t
*al
, size_t width
, size_t height
, const void *surface
) {
133 size_t ps
= pixelSize(atlas
->surface
.PSM
);
138 const char *src
= surface
;
139 char *data
= (char*)atlas
->surface
.Mem
;
141 // advance the pointer to the atlas position start (first pixel)
142 data
+= ps
* (al
->y
* atlas
->allocation
->w
+ al
->x
);
144 size_t rowsize
= width
* ps
;
146 for (y
= 0; y
< height
; ++y
) {
147 memcpy(data
, src
, rowsize
);
148 data
+= ps
* atlas
->allocation
->w
;
153 struct atlas_allocation_t
*atlasPlace(atlas_t
*atlas
, size_t width
, size_t height
, const void *surface
) {
157 struct atlas_allocation_t
*al
= allocPlace(atlas
->allocation
, width
, height
);
162 atlasCopyData(atlas
, al
, width
, height
, surface
);