* don't display a share connection error when listing share
[open-ps2-loader.git] / src / atlas.c
blobb938e8d2aab5f421510181993d1b3bc247860f4b
1 /*
2 Copyright 2010, Volca
3 Licenced under Academic Free License version 3.0
4 Review OpenUsbLd README & LICENSE files for further details.
5 */
7 #include <stdio.h>
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));
13 al->x = x;
14 al->y = y;
15 al->w = width;
16 al->h = height;
18 al->leaf1 = NULL;
19 al->leaf2 = NULL;
21 return al;
24 static inline void allocFree(struct atlas_allocation_t *alloc) {
25 if (!alloc)
26 return;
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);
35 free(alloc);
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) {
46 // do we fit?
47 if (!ALLOC_FITS(alloc, width, height))
48 return NULL;
50 if (ALLOC_ISFREE(alloc)) {
51 // extra space
52 size_t dx = alloc->w - width;
53 size_t dy = alloc->h - height;
55 // make the wider piece also longer - less wasted space
56 if (dx < dy) {
57 alloc->leaf1 = allocNew(alloc->x + width, alloc->y, dx, height);
58 alloc->leaf2 = allocNew(alloc->x, alloc->y + height, alloc->w, dy);
59 } else {
60 alloc->leaf1 = allocNew(alloc->x, alloc->y + height, width, dy);
61 alloc->leaf2 = allocNew(alloc->x + width, alloc->y, dx, alloc->h);
64 return alloc;
65 } else {
66 // already occupied. Try children
67 struct atlas_allocation_t* p = allocPlace(alloc->leaf1, width, height);
68 if (p)
69 return p;
71 p = allocPlace(alloc->leaf2, width, height);
72 if (p)
73 return p;
76 return NULL;
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);
102 return atlas;
105 void atlasFree(atlas_t *atlas) {
106 if (!atlas)
107 return;
109 allocFree(atlas->allocation);
110 atlas->allocation = NULL;
112 free(atlas->surface.Mem);
113 atlas->surface.Mem = NULL;
115 free(atlas);
118 static size_t pixelSize(u8 psm) {
119 switch (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;
125 default:
126 return 0;
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) {
132 int y;
133 size_t ps = pixelSize(atlas->surface.PSM);
135 if (!ps)
136 return;
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;
149 src += ps * width;
153 struct atlas_allocation_t *atlasPlace(atlas_t *atlas, size_t width, size_t height, const void *surface) {
154 if (!surface)
155 return NULL;
157 struct atlas_allocation_t *al = allocPlace(atlas->allocation, width, height);
159 if (!al)
160 return NULL;
162 atlasCopyData(atlas, al, width, height, surface);
164 return al;