Clean up interface and add prefixes to everything
Francesco Pasa 10 months ago
Francesco Pasa 10 months ago
examples/shapes.c M +16 -16
6 options.clear_color.r = 0.02;
7 options.clear_color.g = 0.02;
8 options.clear_color.b = 0.02;
9- AlbaWindow* window = create_window(&options);
10+ AlbaWindow* window = alba_create_window(&options);
11
12 const AlbaVector tri_vertices[] = {
13 100, 100,
24 {{1, 1, 1, 0.2}, {-1, -1}},
25 };
26 uint32_t indices[] = {0, 1, 2, 0, 3, 4};
27- draw_triangles_indexed(window, 5, tri_vertices, attributes, 6, indices);
28+ alba_draw_triangles_indexed(window, 5, tri_vertices, attributes, 6, indices);
29
30 const AlbaColor blue = {0, 0.4, 1, 1};
31- draw_rect_aa(window, 350, 100, 500, 150, blue);
32+ alba_draw_rect_aa(window, 350, 100, 500, 150, blue);
33
34 const float rect_vertices[] = {350, 300, 500, 350, 450, 400, 300, 350};
35- draw_quad(window, rect_vertices, blue);
36+ alba_draw_quad(window, rect_vertices, blue);
37
38- draw_regular_polygon(window, 5, 320, 240, 20, blue);
39- draw_circle(window, 400, 240, 5, blue);
40- draw_circle(window, 420, 240, 6, blue);
41- draw_circle(window, 440, 240, 7, blue);
42- draw_circle(window, 460, 240, 10, blue);
43- draw_circle(window, 480, 240, 15, blue);
44- draw_circle(window, 500, 240, 20, blue);
45- draw_circle(window, 400, 640, 200, blue);
46+ alba_draw_regular_polygon(window, 5, 320, 240, 20, blue);
47+ alba_draw_circle(window, 400, 240, 5, blue);
48+ alba_draw_circle(window, 420, 240, 6, blue);
49+ alba_draw_circle(window, 440, 240, 7, blue);
50+ alba_draw_circle(window, 460, 240, 10, blue);
51+ alba_draw_circle(window, 480, 240, 15, blue);
52+ alba_draw_circle(window, 500, 240, 20, blue);
53+ alba_draw_circle(window, 400, 640, 200, blue);
54
55- draw_rounded_rect_aa(window, 350, 30, 500, 80, 10, blue);
56+ alba_draw_rounded_rect_aa(window, 350, 30, 500, 80, 10, blue);
57
58- while (!window_should_close(window))
59+ while (!alba_window_should_close(window))
60 {
61- window_render(window);
62+ alba_window_render(window);
63 }
64
65- window_release(window);
66+ alba_window_release(window);
67 alba_release();
68 }
examples/text.c M +6 -6
7 options.clear_color.r = 0.02;
8 options.clear_color.g = 0.02;
9 options.clear_color.b = 0.02;
10- AlbaWindow* window = create_window(&options);
11+ AlbaWindow* window = alba_create_window(&options);
12
13- draw_text(window, (AlbaVector){100, 100}, (AlbaColor)YELLOW, 0, "7 lm francesco");
14+ alba_draw_text(window, (AlbaVector){100, 100}, (AlbaColor)YELLOW, 0, "7 lm francesco");
15 // draw_text(window, (AlbaVector){100, 200}, (AlbaColor)WHITE, 0, "ß 🍔");
16- draw_text(window, (AlbaVector){100, 200}, (AlbaColor)CYAN, 0,
17+ alba_draw_text(window, (AlbaVector){100, 200}, (AlbaColor)CYAN, 0,
18 "DESCRIPTION\n The malloc() function allocates size bytes and returns a pointer to the allocated memory. The memory is not initialized. If size is 0, then malloc() returns either NULL, or a unique pointer value that can later be successfully passed to free(). The free() function frees the memory space pointed to by ptr, which must have been returned by a previous call to malloc(), calloc(), or realloc(). Otherwise, or if free(ptr) has already been called before, undefined behavior occurs. If ptr is NULL, no operation is performed. The calloc() function allocates memory for an array of nmemb elements of size bytes each and returns a pointer to the allocated memory. The memory is set to zero. If nmemb or size is 0, then calloc() returns either NULL, or a unique pointer value that can later be successfully passed to free(). If the multiplication of nmemb and size would result in integer overflow, then calloc() returns an error. By contrast, an integer overflow would not be detected in the following call to malloc(), with the result that an incorrectly sized block of memory would be allocated: malloc(nmemb * size); The realloc() function changes the size of the memory block pointed to by ptr to size bytes. The contents will be unchanged in the range from the start of the region up to the minimum of the old and new sizes. If the new size is larger than the old size, the added memory will not be initialized. If ptr is NULL, then the call is equivalent to malloc(size), for all values of size; if size is equal to zero, and ptr is not NULL, then the call is equivalent to free(ptr). Unless ptr is NULL, it must have been returned by an earlier call to malloc(), calloc(), or realloc(). If the area pointed to was moved, a free(ptr) is done. The reallocarray() function changes the size of the memory block pointed to by ptr to be large enough for an array of nmemb elements, each of which is size bytes. It is equivalent to the call realloc(ptr, nmemb * size); However, unlike that realloc() call, reallocarray() fails safely in the case where the multiplication would overflow. If such an overflow occurs, reallocarray() returns NULL, sets errno to ENOMEM, and leaves the original block of memory unchanged. RETURN VALUE The malloc() and calloc() functions return a pointer to the allocated memory, which is suitably aligned for any built-in type. On error, these functions return NULL. N");
19
20- while (!window_should_close(window))
21+ while (!alba_window_should_close(window))
22 {
23- window_render(window);
24+ alba_window_render(window);
25 }
26
27- window_release(window);
28+ alba_window_release(window);
29 alba_release();
30 }
include/alba.h M +42 -71
13 uint64_t length;
14 uint64_t capacity;
15 void* data;
16-} DynArray;
17-
18-DynArray dynarray_new(uint64_t element_size, uint64_t capacity);
19-void dynarray_reserve(DynArray* array, uint64_t request);
20-void dynarray_append(DynArray* array, const void* value);
21-void dynarray_extend(DynArray* array, uint64_t size, const void* data);
22-void dynarray_release(const DynArray* array);
23-void dynarray_clear(DynArray* array);
24-void dynarray_sort(const DynArray* array, uint32_t (*is_before_pivot)(void* pivot, void* elem));
25-void dynarray_print(const DynArray* array, void (*print_element)(void* element));
26-
27-// Misc
28+} AlbaDynArray;
29+
30+AlbaDynArray dynarray_new(uint64_t element_size, uint64_t capacity);
31+void alba_dynarray_reserve(AlbaDynArray* array, uint64_t request);
32+void alba_dynarray_append(AlbaDynArray* array, const void* value);
33+void alba_dynarray_extend(AlbaDynArray* array, uint64_t size, const void* data);
34+void alba_dynarray_release(const AlbaDynArray* array);
35+void alba_dynarray_clear(AlbaDynArray* array);
36+void alba_dynarray_sort(const AlbaDynArray* array, uint32_t (*is_before_pivot)(void* pivot, void* elem));
37+void alba_dynarray_print(const AlbaDynArray* array, void (*print_element)(void* element));
38+
39+// Helper structures
40 typedef struct
41 {
42 float r, g, b, a;
40 #define MAGENTA {1, 0, 1, 1}
41 #define CYAN {0, 1, 1, 1}
42
43-void color_print(const AlbaColor* color);
44+void alba_color_print(const AlbaColor* color);
45
46 typedef struct
47 {
48 float x, y;
49 } AlbaVector;
50
51-void vector_print(const AlbaVector* vector);
52+void alba_vector_print(const AlbaVector* vector);
53
54-inline AlbaVector vector_add(const AlbaVector a, const AlbaVector b)
55+inline AlbaVector alba_vector_add(const AlbaVector a, const AlbaVector b)
56 {
57 return (AlbaVector){a.x + b.x, a.y + b.y};
58 }
59
60-inline AlbaVector vector_sub(const AlbaVector a, const AlbaVector b)
61+inline AlbaVector alba_vector_sub(const AlbaVector a, const AlbaVector b)
62 {
63 return (AlbaVector){a.x - b.x, a.y - b.y};
64 }
65
66-inline AlbaVector vector_mul(const AlbaVector a, const AlbaVector b)
67+inline AlbaVector alba_vector_mul(const AlbaVector a, const AlbaVector b)
68 {
69 return (AlbaVector){a.x * b.x, a.y * b.y};
70 }
71
72-inline AlbaVector vector_div(const AlbaVector a, const AlbaVector b)
73+inline AlbaVector alba_vector_div(const AlbaVector a, const AlbaVector b)
74 {
75 return (AlbaVector){a.x / b.x, a.y / b.y};
76 }
75 AlbaVector uv;
76 } AlbaAttribute;
77
78-void attribute_print(const AlbaAttribute* attribute);
79+void alba_attribute_print(const AlbaAttribute* attribute);
80
81 // Window
82 typedef struct
86 AlbaColor clear_color;
87 } AlbaWindowOptions;
88
89-// TODO: make opaque
90-typedef struct
91-{
92- // if set, the next frame will update the buffers
93- int dirty;
94- DynArray new_vertices;
95- WGPUBuffer vertices;
96- DynArray new_attributes;
97- WGPUBuffer attributes;
98- DynArray new_indices;
99- WGPUBuffer indices;
100- WGPUBuffer uniforms;
101- WGPUTexture texture;
102- WGPURenderPipeline pipeline;
103- WGPUBindGroup bind_group;
104-} RenderPassData;
105-
106-// TODO: make opaque
107-typedef struct
108-{
109- AlbaWindowOptions options;
110- GLFWwindow* glfw_window;
111- AlbaVector size;
112- AlbaVector scale;
113- WGPUInstance instance;
114- WGPUSurface surface;
115- WGPUAdapter adapter;
116- WGPUDevice device;
117- WGPUQueue queue;
118- WGPUShaderModule shaders;
119- RenderPassData drawing;
120- RenderPassData text;
121-} AlbaWindow;
122-
123-AlbaWindow* create_window(const AlbaWindowOptions* options);
124-uint32_t window_should_close(const AlbaWindow* window);
125+typedef struct RenderPassDataImpl RenderPassData;
126+typedef struct AlbaWindowImpl AlbaWindow;
127+
128+AlbaWindow* alba_create_window(const AlbaWindowOptions* options);
129+uint32_t alba_window_should_close(const AlbaWindow* window);
130+// TODO: think about API here, use AlbaVector
131 // Returns window size, in scaled coordinates (e.g. will honor
132 // the windowing system scaling). The point at this coordinate
133 // is at the bottom right of the window.
134-void window_get_size(const AlbaWindow* window, float* width, float* height);
135-void window_render(AlbaWindow* window);
136-void window_release(AlbaWindow* window);
137+void alba_window_get_size(const AlbaWindow* window, float* width, float* height);
138+void alba_window_render(AlbaWindow* window);
139+void alba_window_release(AlbaWindow* window);
140
141 void alba_release();
142
143 // Low level drawing
144-void draw_triangles_indexed(
145+void alba_draw_triangles_indexed(
146 AlbaWindow* window,
147 uint32_t num_vertices,
148 const AlbaVector* vertices,
110 uint32_t num_indices,
111 uint32_t* indices
112 );
113-void draw_triangles(
114+void alba_draw_triangles(
115 AlbaWindow* window,
116 uint32_t num_vertices,
117 const AlbaVector* vertices,
118 );
119
120 // Higher level drawing
121-void draw_triangle(AlbaWindow* window, const AlbaVector vertices[3], AlbaColor color);
122-void draw_quad(AlbaWindow* window, const AlbaVector vertices[4], AlbaColor color);
123-void draw_rect_aa(AlbaWindow* window, float x0, float y0, float x1, float y1, AlbaColor color);
124+void alba_draw_triangle(AlbaWindow* window, const AlbaVector vertices[3], AlbaColor color);
125+void alba_draw_quad(AlbaWindow* window, const AlbaVector vertices[4], AlbaColor color);
126+void alba_draw_rect_aa(AlbaWindow* window, float x0, float y0, float x1, float y1, AlbaColor color);
127
128-void generate_regular_polygon(DynArray* array, uint32_t num_sides, float x, float y, float r);
129-void generate_circle(DynArray* array, float x, float y, float r);
130-void generate_rounded_rect_aa(DynArray* array, float x0, float y0, float x1, float y1, float r);
131+void alba_generate_regular_polygon(AlbaDynArray* array, uint32_t num_sides, float x, float y, float r);
132+void alba_generate_circle(AlbaDynArray* array, float x, float y, float r);
133+void alba_generate_rounded_rect_aa(AlbaDynArray* array, float x0, float y0, float x1, float y1, float r);
134
135-void draw_concave_polygon(AlbaWindow* window, float x, float y, const DynArray* contour, AlbaColor color);
136-void draw_regular_polygon(AlbaWindow* window, uint32_t num_sides, float x, float y, float r, AlbaColor color);
137-void draw_circle(AlbaWindow* window, float x, float y, float r, AlbaColor color);
138-void draw_rounded_rect_aa(AlbaWindow* window, float x0, float y0, float x1, float y1, float r, AlbaColor color);
139+void alba_draw_concave_polygon(AlbaWindow* window, float x, float y, const AlbaDynArray* contour, AlbaColor color);
140+void alba_draw_regular_polygon(AlbaWindow* window, uint32_t num_sides, float x, float y, float r, AlbaColor color);
141+void alba_draw_circle(AlbaWindow* window, float x, float y, float r, AlbaColor color);
142+void alba_draw_rounded_rect_aa(AlbaWindow* window, float x0, float y0, float x1, float y1, float r, AlbaColor color);
143
144-void draw_text(
145+// Text drawing
146+void alba_draw_text(
147 AlbaWindow* window,
148 AlbaVector pos, AlbaColor color,
149 uint64_t length, const char* text
src/atlas.c M +22 -22
9
10 int compare_glyph(const void* va, const void* vb, void* udata)
11 {
12- const Glyph* a = va;
13- const Glyph* b = vb;
14+ const AlbaGlyph* a = va;
15+ const AlbaGlyph* b = vb;
16 return a->character - b->character;
17 }
18
19 void free_glyph(void* vglyph)
20 {
21- const Glyph* glyph = vglyph;
22+ const AlbaGlyph* glyph = vglyph;
23 free(glyph->bitmap.buffer);
24 }
25
26-Atlas atlas_new(const uint32_t capacity)
27+AlbaAtlas atlas_new(const uint32_t capacity)
28 {
29- Atlas atlas = {0};
30- atlas.glyphs = hashmap_new(sizeof(Glyph), capacity, 0, 0, hash_glyph, compare_glyph, free_glyph, NULL);
31+ AlbaAtlas atlas = {0};
32+ atlas.glyphs = hashmap_new(sizeof(AlbaGlyph), capacity, 0, 0, hash_glyph, compare_glyph, free_glyph, NULL);
33 if (capacity != 0)
34 {
35 atlas_reserve(&atlas, capacity);
31 return atlas;
32 }
33
34-void atlas_reserve(Atlas* atlas, const uint32_t capacity)
35+void atlas_reserve(AlbaAtlas* atlas, const uint32_t capacity)
36 {
37- dynarray_reserve(&atlas->glyph_sizes, capacity * 4);
38+ alba_dynarray_reserve(&atlas->glyph_sizes, capacity * 4);
39 }
40
41-void atlas_append(Atlas* atlas, const FT_Face face, const uint32_t character)
42+void atlas_append(AlbaAtlas* atlas, const FT_Face face, const uint32_t character)
43 {
44 const FT_Long glyph_index = FT_Load_Char(face, character, FT_LOAD_RENDER);
45
46 const FT_Bitmap* bitmap = &face->glyph->bitmap;
47- Glyph glyph = {
48+ AlbaGlyph glyph = {
49 .character = character,
50 .glyph_index = glyph_index,
51 .metrics = face->glyph->metrics,
61
62 uint32_t sort_by_height_desc(void* vpivot, void* velem)
63 {
64- const Glyph** pivot = vpivot;
65- const Glyph** elem = velem;
66+ const AlbaGlyph** pivot = vpivot;
67+ const AlbaGlyph** elem = velem;
68 return (*elem)->bitmap.rows > (*pivot)->bitmap.rows;
69 }
70
138 }
139
140 // TODO: mutex?
141-void atlas_generate_image(Atlas* atlas)
142+void atlas_generate_image(AlbaAtlas* atlas)
143 {
144 if (atlas->dirty == 0) return;
145
146 // Sort caracters by height
147 size_t iter = 0;
148- Glyph* glyph;
149- DynArray glyphs = dynarray_new(sizeof(Glyph*), hashmap_count(atlas->glyphs));
150+ AlbaGlyph* glyph;
151+ AlbaDynArray glyphs = dynarray_new(sizeof(AlbaGlyph*), hashmap_count(atlas->glyphs));
152 while (hashmap_iter(atlas->glyphs, &iter, (void**)&glyph))
153 {
154- dynarray_append(&glyphs, &glyph);
155+ alba_dynarray_append(&glyphs, &glyph);
156 }
157- dynarray_sort(&glyphs, sort_by_height_desc);
158+ alba_dynarray_sort(&glyphs, sort_by_height_desc);
159
160 // Calculate minimum size that fits the characters
161 uint32_t image_size = 256;
162 uint32_t row_height = 0;
163 for (uint32_t i = 0; i < glyphs.length; i++)
164 {
165- glyph = ((Glyph**)glyphs.data)[i];
166+ glyph = ((AlbaGlyph**)glyphs.data)[i];
167
168 // Go to new line
169 if (x + glyph->bitmap.width > image_size)
206 uint32_t row_height = 0;
207 for (uint32_t i = 0; i < glyphs.length; i++)
208 {
209- glyph = ((Glyph**)glyphs.data)[i];
210+ glyph = ((AlbaGlyph**)glyphs.data)[i];
211
212 if (x + glyph->bitmap.width > image_size)
213 {
233
234 // write_png("test.png", image_size, image_size, 32, atlas->image);
235
236- dynarray_release(&glyphs);
237+ alba_dynarray_release(&glyphs);
238
239 atlas->dirty = 0;
240 }
241
242-void atlas_release(const Atlas* atlas)
243+void atlas_release(const AlbaAtlas* atlas)
244 {
245 hashmap_free(atlas->glyphs);
246- dynarray_release(&atlas->glyph_sizes);
247+ alba_dynarray_release(&atlas->glyph_sizes);
248 if (atlas->image != NULL)
249 {
250 free(atlas->image);
src/drawing.c M +44 -44
19 {
20 const uint32_t offset = data->new_vertices.length;
21
22- dynarray_extend(&data->new_vertices, num_vertices, vertices);
23- dynarray_extend(&data->new_attributes, num_vertices, attributes);
24+ alba_dynarray_extend(&data->new_vertices, num_vertices, vertices);
25+ alba_dynarray_extend(&data->new_attributes, num_vertices, attributes);
26
27 if (offset > 0)
28 {
30 indices[i] += offset;
31 }
32 }
33- dynarray_extend(&data->new_indices, num_indices, indices);
34+ alba_dynarray_extend(&data->new_indices, num_indices, indices);
35
36 data->dirty = 1;
37 }
38
39-void draw_triangles_indexed(
40+void alba_draw_triangles_indexed(
41 AlbaWindow* window,
42 const uint32_t num_vertices,
43 const AlbaVector* vertices,
47 draw_triangles_indexed_render_pass(&window->drawing, num_vertices, vertices, attributes, num_indices, indices);
48 }
49
50-void draw_triangles(
51+void alba_draw_triangles(
52 AlbaWindow* window,
53 const uint32_t num_vertices,
54 const AlbaVector* vertices,
69 indices[i] = i;
70 }
71
72- draw_triangles_indexed(window, num_vertices, vertices, attributes, num_vertices, indices);
73+ alba_draw_triangles_indexed(window, num_vertices, vertices, attributes, num_vertices, indices);
74
75 free(indices);
76 }
77
78-void draw_triangle(AlbaWindow* window, const AlbaVector vertices[3], const AlbaColor color)
79+void alba_draw_triangle(AlbaWindow* window, const AlbaVector vertices[3], const AlbaColor color)
80 {
81 const AlbaAttribute attributes[] = {
82 color, NO_TEXTURE,
83 };
84 // Does not try to consider winding order
85 uint32_t indices[] = {0, 1, 2};
86- draw_triangles_indexed(window, 3, vertices, attributes, 3, indices);
87+ alba_draw_triangles_indexed(window, 3, vertices, attributes, 3, indices);
88 }
89
90-void draw_quad(AlbaWindow* window, const AlbaVector vertices[4], const AlbaColor color)
91+void alba_draw_quad(AlbaWindow* window, const AlbaVector vertices[4], const AlbaColor color)
92 {
93 const AlbaAttribute attributes[] = {
94 color, NO_TEXTURE,
96 };
97 // Does not try to consider winding order
98 uint32_t indices[] = {0, 1, 2, 0, 2, 3};
99- draw_triangles_indexed(window, 4, vertices, attributes, 6, indices);
100+ alba_draw_triangles_indexed(window, 4, vertices, attributes, 6, indices);
101 }
102
103-void draw_rect_aa(
104+void alba_draw_rect_aa(
105 AlbaWindow* window,
106 const float x0, const float y0, const float x1, const float y1,
107 const AlbaColor color
122 x1, y1,
123 x1, y0,
124 };
125- draw_quad(window, vertices, color);
126+ alba_draw_quad(window, vertices, color);
127 }
128
129-void generate_regular_polygon(
130- DynArray* array, const uint32_t num_sides,
131+void alba_generate_regular_polygon(
132+ AlbaDynArray* array, const uint32_t num_sides,
133 const float x, const float y, const float r)
134 {
135- dynarray_reserve(array, array->length + num_sides);
136+ alba_dynarray_reserve(array, array->length + num_sides);
137
138 const float step_angle = 2 * PI / num_sides;
139 for (uint32_t i = 0; i < num_sides; i++)
140 {
141- dynarray_append(
142+ alba_dynarray_append(
143 array,
144 &(AlbaVector){
145 x + r * sin(step_angle * i),
144 }
145 }
146
147-void generate_circle(DynArray* array, const float x, const float y, const float r)
148+void alba_generate_circle(AlbaDynArray* array, const float x, const float y, const float r)
149 {
150 const uint32_t num_sides = round(PI / acos(1 - MAX_ERROR / r));
151- generate_regular_polygon(array, num_sides, x, y, r);
152+ alba_generate_regular_polygon(array, num_sides, x, y, r);
153 }
154
155-void generate_rounded_rect_aa(
156- DynArray* array,
157+void alba_generate_rounded_rect_aa(
158+ AlbaDynArray* array,
159 const float x0, const float y0, const float x1, const float y1,
160 float r
161 )
165 if (x1 - x0 < r) r = (x1 - x0) / 2;
166 if (y1 - y0 < r) r = (y1 - y0) / 2;
167
168- dynarray_reserve(array, array->length + num_sides);
169+ alba_dynarray_reserve(array, array->length + num_sides);
170
171 uint32_t i = 0;
172 for (; i < num_sides_per_corner + 1; i++)
173 {
174- dynarray_append(
175+ alba_dynarray_append(
176 array, &(AlbaVector){
177 x0 + r - r * sin(step_angle * i),
178 y0 + r - r * cos(step_angle * i)
180
181 for (; i < 2 * num_sides_per_corner + 1; i++)
182 {
183- dynarray_append(
184+ alba_dynarray_append(
185 array, &(AlbaVector){
186 x0 + r - r * sin(step_angle * i),
187 y1 - r - r * cos(step_angle * i)
190
191 for (; i < 3 * num_sides_per_corner + 1; i++)
192 {
193- dynarray_append(
194+ alba_dynarray_append(
195 array, &(AlbaVector){
196 x1 - r - r * sin(step_angle * i),
197 y1 - r - r * cos(step_angle * i)
200
201 for (; i < 4 * num_sides_per_corner + 1; i++)
202 {
203- dynarray_append(
204+ alba_dynarray_append(
205 array, &(AlbaVector){
206 x1 - r - r * sin(step_angle * i),
207 y0 + r - r * cos(step_angle * i)
208 }
209 }
210
211-void draw_concave_polygon(AlbaWindow* window, const float x, const float y, const DynArray* contour,
212+void alba_draw_concave_polygon(AlbaWindow* window, const float x, const float y, const AlbaDynArray* contour,
213 const AlbaColor color)
214 {
215 const uint32_t num_sides = contour->length;
216 const uint32_t num_triangles = num_sides - 2;
217
218- DynArray attributes = dynarray_new(sizeof(AlbaAttribute), num_sides);
219+ AlbaDynArray attributes = dynarray_new(sizeof(AlbaAttribute), num_sides);
220 for (uint32_t i = 0; i < num_sides; i++)
221 {
222- dynarray_append(&attributes, &(AlbaAttribute){color, NO_TEXTURE});
223+ alba_dynarray_append(&attributes, &(AlbaAttribute){color, NO_TEXTURE});
224 }
225
226 uint32_t* indices = malloc(num_triangles * 3 * sizeof(uint32_t));
228 indices[i * 3 + 2] = i + 2;
229 }
230
231- draw_triangles_indexed(
232+ alba_draw_triangles_indexed(
233 window,
234 num_sides, contour->data, attributes.data,
235 num_triangles * 3, indices
237 free(indices);
238 }
239
240-void draw_regular_polygon(
241+void alba_draw_regular_polygon(
242 AlbaWindow* window, const uint32_t num_sides,
243 const float x, const float y, const float r,
244 const AlbaColor color
250 exit(1);
251 }
252
253- DynArray polygon = dynarray_new(sizeof(AlbaVector), 0);
254- generate_regular_polygon(&polygon, num_sides, x, y, r);
255- draw_concave_polygon(window, x, y, &polygon, color);
256- dynarray_release(&polygon);
257+ AlbaDynArray polygon = dynarray_new(sizeof(AlbaVector), 0);
258+ alba_generate_regular_polygon(&polygon, num_sides, x, y, r);
259+ alba_draw_concave_polygon(window, x, y, &polygon, color);
260+ alba_dynarray_release(&polygon);
261 }
262
263-void draw_circle(AlbaWindow* window, const float x, const float y, const float r, const AlbaColor color)
264+void alba_draw_circle(AlbaWindow* window, const float x, const float y, const float r, const AlbaColor color)
265 {
266- DynArray circle = dynarray_new(sizeof(AlbaVector), 0);
267- generate_circle(&circle, x, y, r);
268- draw_concave_polygon(window, x, y, &circle, color);
269- dynarray_release(&circle);
270+ AlbaDynArray circle = dynarray_new(sizeof(AlbaVector), 0);
271+ alba_generate_circle(&circle, x, y, r);
272+ alba_draw_concave_polygon(window, x, y, &circle, color);
273+ alba_dynarray_release(&circle);
274 }
275
276
277-void draw_rounded_rect_aa(
278+void alba_draw_rounded_rect_aa(
279 AlbaWindow* window,
280 const float x0, const float y0, const float x1, const float y1,
281 const float r, const AlbaColor color)
282 {
283 if (r == 0)
284 {
285- draw_rect_aa(window, x0, y0, x1, y1, color);
286+ alba_draw_rect_aa(window, x0, y0, x1, y1, color);
287 return;
288 }
289
290- DynArray contour = dynarray_new(sizeof(AlbaVector), 0);
291- generate_rounded_rect_aa(&contour, x0, y0, x1, y1, r);
292- draw_concave_polygon(window, (x0 + x1) / 2, (y0 + y1) / 2, &contour, color);
293+ AlbaDynArray contour = dynarray_new(sizeof(AlbaVector), 0);
294+ alba_generate_rounded_rect_aa(&contour, x0, y0, x1, y1, r);
295+ alba_draw_concave_polygon(window, (x0 + x1) / 2, (y0 + y1) / 2, &contour, color);
296 }
src/dynarray.c M +11 -11
5 #include <stdlib.h>
6 #include <string.h>
7
8-DynArray dynarray_new(const uint64_t element_size, const uint64_t capacity)
9+AlbaDynArray dynarray_new(const uint64_t element_size, const uint64_t capacity)
10 {
11- DynArray array = {0};
12+ AlbaDynArray array = {0};
13 array.element_size = element_size;
14 if (capacity > 0)
15 {
17 return array;
18 }
19
20-void dynarray_reserve(DynArray* array, const uint64_t request)
21+void alba_dynarray_reserve(AlbaDynArray* array, const uint64_t request)
22 {
23 if (array->capacity > request) return;
24 if (array->capacity == 0) array->capacity = 16;
28 array->data = reallocarray(array->data, array->capacity, array->element_size);
29 }
30
31-void dynarray_append(DynArray* array, const void* value)
32+void alba_dynarray_append(AlbaDynArray* array, const void* value)
33 {
34- dynarray_extend(array, 1, value);
35+ alba_dynarray_extend(array, 1, value);
36 }
37
38-void dynarray_extend(DynArray* array, const uint64_t size, const void* data)
39+void alba_dynarray_extend(AlbaDynArray* array, const uint64_t size, const void* data)
40 {
41- dynarray_reserve(array, array->length + size);
42+ alba_dynarray_reserve(array, array->length + size);
43 memcpy(array->data + array->length * array->element_size, data, size * array->element_size);
44 array->length += size;
45 }
46
47-void dynarray_release(const DynArray* array)
48+void alba_dynarray_release(const AlbaDynArray* array)
49 {
50 free(array->data);
51 }
52
53-void dynarray_clear(DynArray* array)
54+void alba_dynarray_clear(AlbaDynArray* array)
55 {
56 array->length = 0;
57 }
93 quicksort(element_size, length - num_elem_before - 1, data + size_before + element_size, is_before_pivot, temp);
94 }
95
96-void dynarray_sort(const DynArray* array, uint32_t (*is_before_pivot)(void* pivot, void* elem))
97+void alba_dynarray_sort(const AlbaDynArray* array, uint32_t (*is_before_pivot)(void* pivot, void* elem))
98 {
99 void* temp = malloc(array->element_size);
100 quicksort(array->element_size, array->length, array->data, is_before_pivot, temp);
101 free(temp);
102 }
103
104-void dynarray_print(const DynArray* array, void (*print_element)(void* element))
105+void alba_dynarray_print(const AlbaDynArray* array, void (*print_element)(void* element))
106 {
107 printf("len: %lu\n", array->length);
108 for (uint64_t i = 0; i < array->length; i++)
src/glfw_surface.c M +1
src/helpers.c M +5 -5
2
3 #include <stdio.h>
4
5-void color_print(const AlbaColor* color)
6+void alba_color_print(const AlbaColor* color)
7 {
8 printf("AlbaColor{%f, %f, %f, %f}\n", color->r, color->g, color->b, color->a);
9 }
10
11-void vector_print(const AlbaVector* vector)
12+void alba_vector_print(const AlbaVector* vector)
13 {
14 printf("AlbaVector{%f, %f}\n", vector->x, vector->y);
15 }
16
17-void attribute_print(const AlbaAttribute* attribute)
18+void alba_attribute_print(const AlbaAttribute* attribute)
19 {
20 printf("AlbaAttribute{\n ");
21- color_print(&attribute->color);
22+ alba_color_print(&attribute->color);
23 printf(" ");
24- vector_print(&attribute->uv);
25+ alba_vector_print(&attribute->uv);
26 printf("}\n");
27 }
src/internal.h M +40 -8
7
8 #define NO_TEXTURE {-1, -1}
9
10+typedef struct RenderPassDataImpl
11+{
12+ // if set, the next frame will update the buffers
13+ int dirty;
14+ AlbaDynArray new_vertices;
15+ WGPUBuffer vertices;
16+ AlbaDynArray new_attributes;
17+ WGPUBuffer attributes;
18+ AlbaDynArray new_indices;
19+ WGPUBuffer indices;
20+ WGPUBuffer uniforms;
21+ WGPUTexture texture;
22+ WGPURenderPipeline pipeline;
23+ WGPUBindGroup bind_group;
24+} RenderPassData;
25+
26+typedef struct AlbaWindowImpl
27+{
28+ AlbaWindowOptions options;
29+ GLFWwindow* glfw_window;
30+ AlbaVector size;
31+ AlbaVector scale;
32+ WGPUInstance instance;
33+ WGPUSurface surface;
34+ WGPUAdapter adapter;
35+ WGPUDevice device;
36+ WGPUQueue queue;
37+ WGPUShaderModule shaders;
38+ RenderPassData drawing;
39+ RenderPassData text;
40+} AlbaWindow;
41+
42 // Atlas
43 typedef struct
44 {
48 FT_Bitmap bitmap;
49 AlbaVector start;
50 AlbaVector end;
51-} Glyph;
52+} AlbaGlyph;
53
54 typedef struct
55 {
56 struct hashmap* glyphs;
57 int dirty;
58- DynArray glyph_sizes; // in w, h order
59+ AlbaDynArray glyph_sizes; // in w, h order
60 AlbaVector size;
61 uint8_t* image;
62-} Atlas;
63+} AlbaAtlas;
64
65-Atlas atlas_new(uint32_t capacity);
66-void atlas_reserve(Atlas* atlas, uint32_t capacity);
67-void atlas_append(Atlas* atlas, FT_Face face, uint32_t character);
68-void atlas_generate_image(Atlas* atlas);
69-void atlas_release(const Atlas* atlas);
70+AlbaAtlas atlas_new(uint32_t capacity);
71+void atlas_reserve(AlbaAtlas* atlas, uint32_t capacity);
72+void atlas_append(AlbaAtlas* atlas, FT_Face face, uint32_t character);
73+void atlas_generate_image(AlbaAtlas* atlas);
74+void atlas_release(const AlbaAtlas* atlas);
75
76 // Helpers
77 WGPUTexture create_texture(
src/text.c M +12 -12
10
11 static FT_Library freetype = NULL;
12 static FT_Face roboto = NULL;
13-Atlas atlas;
14+AlbaAtlas atlas;
15 pthread_mutex_t freetype_mutex = PTHREAD_MUTEX_INITIALIZER;
16
17 void initialize_freetype()
48 pthread_mutex_unlock(&freetype_mutex);
49 }
50
51-void atlas_add_chars(Atlas* atlas, uint64_t length, const char* text)
52+void atlas_add_chars(AlbaAtlas* atlas, uint64_t length, const char* text)
53 {
54 for (uint64_t i = 0; i < length; i++)
55 {
62 }
63
64 void atlas_generate_text_geometry(
65- const Atlas* atlas,
66+ const AlbaAtlas* atlas,
67 const AlbaVector pos, const AlbaColor color,
68 uint64_t length, const char* text,
69- DynArray* vertices, DynArray* attributes, DynArray* indices
70+ AlbaDynArray* vertices, AlbaDynArray* attributes, AlbaDynArray* indices
71 )
72 {
73 AlbaVector current = pos;
73 {
74 // TODO: mutex?
75 const FT_Long character = text[i]; // TODO: unicode
76- const Glyph* glyph = hashmap_get(atlas->glyphs, &character);
77+ const AlbaGlyph* glyph = hashmap_get(atlas->glyphs, &character);
78 if (glyph == NULL)
79 {
80 fprintf(stderr, "error: unable to find glyph for character '%s'\n", (char*)&character);
86 current.y - metrics.horiBearingY / 64,
87 };
88 const uint32_t vertex_count = vertices->length;
89- dynarray_extend(
90+ alba_dynarray_extend(
91 vertices, 4, (AlbaVector[]){
92 origin,
93 origin.x, origin.y + metrics.height / 64,
94 origin.x + metrics.width / 64, origin.y,
95 });
96
97- dynarray_extend(
98+ alba_dynarray_extend(
99 attributes, 4, (AlbaAttribute[]){
100 {color, glyph->start},
101 {color, (AlbaVector){glyph->start.x, glyph->end.y}},
102 {color, (AlbaVector){glyph->end.x, glyph->start.y}},
103 });
104
105- dynarray_extend(
106+ alba_dynarray_extend(
107 indices, 6, (uint32_t[]){
108 // first triangle
109 vertex_count,
119 }
120 }
121
122-void draw_text(
123+void alba_draw_text(
124 AlbaWindow* window,
125 const AlbaVector pos, const AlbaColor color,
126 uint64_t length, const char* text
147 );
148 window->text.dirty = 1;
149
150- DynArray vertices = dynarray_new(sizeof(AlbaVector), length * 4);
151- DynArray attributes = dynarray_new(sizeof(AlbaAttribute), length * 4);
152- DynArray indices = dynarray_new(sizeof(uint32_t), length * 6);
153+ AlbaDynArray vertices = dynarray_new(sizeof(AlbaVector), length * 4);
154+ AlbaDynArray attributes = dynarray_new(sizeof(AlbaAttribute), length * 4);
155+ AlbaDynArray indices = dynarray_new(sizeof(uint32_t), length * 6);
156
157 atlas_generate_text_geometry(
158 &atlas,
src/window.c M +10 -10
340 data->new_indices = dynarray_new(sizeof(uint32_t), 0);
341 }
342
343-AlbaWindow* create_window(const AlbaWindowOptions* options)
344+AlbaWindow* alba_create_window(const AlbaWindowOptions* options)
345 {
346 pthread_mutex_lock(&glfw_mutex);
347 if (!glfw_initialized)
417 return window;
418 }
419
420-uint32_t window_should_close(const AlbaWindow* window)
421+uint32_t alba_window_should_close(const AlbaWindow* window)
422 {
423 const int should_close = glfwWindowShouldClose(window->glfw_window);
424 if (!should_close)
427 return should_close;
428 }
429
430-void window_release(AlbaWindow* window)
431+void alba_window_release(AlbaWindow* window)
432 {
433 // TODO: destroy render pass
434 wgpuBufferDestroy(window->drawing.uniforms);
435
436 wgpuBufferDestroy(window->drawing.vertices);
437 wgpuBufferRelease(window->drawing.vertices);
438- dynarray_release(&window->drawing.new_vertices);
439+ alba_dynarray_release(&window->drawing.new_vertices);
440
441 wgpuBufferDestroy(window->drawing.attributes);
442 wgpuBufferRelease(window->drawing.attributes);
443- dynarray_release(&window->drawing.new_attributes);
444+ alba_dynarray_release(&window->drawing.new_attributes);
445
446 wgpuBufferDestroy(window->drawing.indices);
447 wgpuBufferRelease(window->drawing.indices);
448- dynarray_release(&window->drawing.new_indices);
449+ alba_dynarray_release(&window->drawing.new_indices);
450
451 wgpuBindGroupRelease(window->drawing.bind_group);
452 wgpuRenderPipelineRelease(window->drawing.pipeline);
504 }
505 }
506
507-WGPUBuffer update_buffer(const AlbaWindow* window, WGPUBuffer buffer, WGPUBufferUsage usage, DynArray data)
508+WGPUBuffer update_buffer(const AlbaWindow* window, WGPUBuffer buffer, WGPUBufferUsage usage, AlbaDynArray data)
509 {
510 // Deallocate old buffer if any
511 clear_buffer(buffer);
512 // Copy data to new buffer
513 buffer = create_buffer(window, data.length * data.element_size, data.data, usage);
514 // Clear local copy for next frame
515- dynarray_clear(&data);
516+ alba_dynarray_clear(&data);
517 return buffer;
518 }
519
584 wgpuCommandEncoderRelease(encoder);
585 }
586
587-void window_render(AlbaWindow* window)
588+void alba_window_render(AlbaWindow* window)
589 {
590 WGPUSurfaceTexture frame;
591 wgpuSurfaceGetCurrentTexture(window->surface, &frame);
636 }
637
638
639-void window_get_size(const AlbaWindow* window, float* width, float* height)
640+void alba_window_get_size(const AlbaWindow* window, float* width, float* height)
641 {
642 int raw_width, raw_height;
643 float x_scale, y_scale;
tests/test_dynarray.c M +7 -7
4
5 START_TEST(test_dynarray_new)
6 {
7- DynArray array = dynarray_new(sizeof(float), 0);
8+ AlbaDynArray array = dynarray_new(sizeof(float), 0);
9 ck_assert_int_eq(array.element_size, sizeof(float));
10 ck_assert_int_eq(array.capacity, 0);
11 ck_assert_int_eq(array.length, 0);
14
15 START_TEST(test_dynarray_extend)
16 {
17- DynArray array = dynarray_new(sizeof(float), 0);
18- dynarray_extend(&array, 2, &(float[]){1.0, 2.0});
19+ AlbaDynArray array = dynarray_new(sizeof(float), 0);
20+ alba_dynarray_extend(&array, 2, &(float[]){1.0, 2.0});
21
22 ck_assert_int_eq(array.element_size, sizeof(float));
23 ck_assert_int_eq(array.capacity, 16);
23 ck_assert_float_eq(((float*)array.data)[0], 1.0);
24 ck_assert_float_eq(((float*)array.data)[1], 2.0);
25
26- dynarray_extend(&array, 2, &(float[]){3.0, 4.0});
27+ alba_dynarray_extend(&array, 2, &(float[]){3.0, 4.0});
28 ck_assert_int_eq(array.capacity, 16);
29 ck_assert_int_eq(array.length, 4);
30 ck_assert_float_eq(((float*)array.data)[0], 1.0);
43
44 START_TEST(test_dynarray_sort)
45 {
46- DynArray array = dynarray_new(sizeof(float), 0);
47+ AlbaDynArray array = dynarray_new(sizeof(float), 0);
48 const float values[] = {7, 2.3, 5, 6, 2, 3, 4, 9, 1, 4};
49- dynarray_extend(&array, 10, values);
50+ alba_dynarray_extend(&array, 10, values);
51
52 ck_assert_int_eq(array.element_size, sizeof(float));
53 ck_assert_int_eq(array.length, 10);
54 ck_assert_int_eq(array.capacity, 16);
55
56- dynarray_sort(&array, compare_floats);
57+ alba_dynarray_sort(&array, compare_floats);
58
59 ck_assert_float_eq(((float*)array.data) [0], 1);
60 ck_assert_float_eq(((float*)array.data) [1], 2);