source: mainline/uspace/lib/memgfx/test/memgfx.c@ dbef30f

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since dbef30f was f8375f7, checked in by Jiri Svoboda <jiri@…>, 5 years ago

Communicate memory GC updates via callback function

This is what we want in most use cases. Allows us to expose memory GC
ops directly without interposing on them (greatly simplifying the code).
The previous behavior is easily achieved by supplying the right callback
function.

  • Property mode set to 100644
File size: 7.3 KB
Line 
1/*
2 * Copyright (c) 2020 Jiri Svoboda
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <errno.h>
30#include <gfx/bitmap.h>
31#include <gfx/color.h>
32#include <gfx/coord.h>
33#include <gfx/context.h>
34#include <gfx/render.h>
35#include <io/pixelmap.h>
36#include <mem.h>
37#include <memgfx/memgc.h>
38#include <pcut/pcut.h>
39
40PCUT_INIT;
41
42PCUT_TEST_SUITE(memgfx);
43
44static void test_update_rect(void *arg, gfx_rect_t *rect);
45
46typedef struct {
47 /** True if update was called */
48 bool update_called;
49 /** Update rectangle */
50 gfx_rect_t rect;
51} test_update_t;
52
53/** Test creating and deleting a memory GC */
54PCUT_TEST(create_delete)
55{
56 mem_gc_t *mgc;
57 gfx_rect_t rect;
58 gfx_bitmap_alloc_t alloc;
59 errno_t rc;
60
61 rect.p0.x = 0;
62 rect.p0.y = 0;
63 rect.p1.x = 10;
64 rect.p1.y = 10;
65
66 alloc.pitch = (rect.p1.x - rect.p0.x) * sizeof(uint32_t);
67 alloc.off0 = 0;
68 alloc.pixels = calloc(1, alloc.pitch * (rect.p1.y - rect.p0.y));
69 PCUT_ASSERT_NOT_NULL(alloc.pixels);
70
71 rc = mem_gc_create(&rect, &alloc, NULL, NULL, &mgc);
72 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
73
74 mem_gc_delete(mgc);
75 free(alloc.pixels);
76}
77
78/** Test filling a rectangle in memory GC */
79PCUT_TEST(fill_rect)
80{
81 mem_gc_t *mgc;
82 gfx_rect_t rect;
83 gfx_rect_t frect;
84 gfx_bitmap_alloc_t alloc;
85 gfx_context_t *gc;
86 gfx_color_t *color;
87 gfx_coord2_t pos;
88 pixelmap_t pixelmap;
89 pixel_t pixel;
90 pixel_t expected;
91 test_update_t update;
92 errno_t rc;
93
94 /* Bounding rectangle for memory GC */
95 rect.p0.x = 0;
96 rect.p0.y = 0;
97 rect.p1.x = 10;
98 rect.p1.y = 10;
99
100 alloc.pitch = (rect.p1.x - rect.p0.x) * sizeof(uint32_t);
101 alloc.off0 = 0;
102 alloc.pixels = calloc(1, alloc.pitch * (rect.p1.y - rect.p0.y));
103 PCUT_ASSERT_NOT_NULL(alloc.pixels);
104
105 rc = mem_gc_create(&rect, &alloc, test_update_rect, &update, &mgc);
106 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
107
108 gc = mem_gc_get_ctx(mgc);
109 PCUT_ASSERT_NOT_NULL(gc);
110
111 /* Fill a rectangle */
112
113 rc = gfx_color_new_rgb_i16(0xffff, 0xffff, 0, &color);
114 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
115
116 rc = gfx_set_color(gc, color);
117 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
118
119 frect.p0.x = 2;
120 frect.p0.y = 2;
121 frect.p1.x = 5;
122 frect.p1.y = 5;
123
124 memset(&update, 0, sizeof(update));
125
126 rc = gfx_fill_rect(gc, &frect);
127 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
128
129 pixelmap.width = rect.p1.x - rect.p0.x;
130 pixelmap.height = rect.p1.y - rect.p0.y;
131 pixelmap.data = alloc.pixels;
132
133 /* Check that the pixels of the rectangle are set and no others are */
134 for (pos.y = rect.p0.y; pos.y < rect.p1.y; pos.y++) {
135 for (pos.x = rect.p0.x; pos.x < rect.p1.x; pos.x++) {
136 pixel = pixelmap_get_pixel(&pixelmap, pos.x, pos.y);
137 expected = gfx_pix_inside_rect(&pos, &frect) ?
138 PIXEL(0, 255, 255, 0) : PIXEL(0, 0, 0, 0);
139 PCUT_ASSERT_INT_EQUALS(expected, pixel);
140 }
141 }
142
143 /* Check that the update rect is equal to the filled rect */
144 PCUT_ASSERT_TRUE(update.update_called);
145 PCUT_ASSERT_INT_EQUALS(frect.p0.x, update.rect.p0.x);
146 PCUT_ASSERT_INT_EQUALS(frect.p0.y, update.rect.p0.y);
147 PCUT_ASSERT_INT_EQUALS(frect.p1.x, update.rect.p1.x);
148 PCUT_ASSERT_INT_EQUALS(frect.p1.y, update.rect.p1.y);
149
150 /* TODO: Check clipping once memgc can support pitch != width etc. */
151
152 mem_gc_delete(mgc);
153 free(alloc.pixels);
154}
155
156/** Test rendering a bitmap in memory GC */
157PCUT_TEST(bitmap_render)
158{
159 mem_gc_t *mgc;
160 gfx_rect_t rect;
161 gfx_bitmap_alloc_t alloc;
162 gfx_context_t *gc;
163 gfx_coord2_t pos;
164 gfx_bitmap_params_t params;
165 gfx_bitmap_alloc_t balloc;
166 gfx_bitmap_t *bitmap;
167 pixelmap_t bpmap;
168 pixelmap_t dpmap;
169 pixel_t pixel;
170 pixel_t expected;
171 test_update_t update;
172 errno_t rc;
173
174 /* Bounding rectangle for memory GC */
175 rect.p0.x = 0;
176 rect.p0.y = 0;
177 rect.p1.x = 10;
178 rect.p1.y = 10;
179
180 alloc.pitch = (rect.p1.x - rect.p0.x) * sizeof(uint32_t);
181 alloc.off0 = 0;
182 alloc.pixels = calloc(1, alloc.pitch * (rect.p1.y - rect.p0.y));
183 PCUT_ASSERT_NOT_NULL(alloc.pixels);
184
185 rc = mem_gc_create(&rect, &alloc, test_update_rect, &update, &mgc);
186 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
187
188 gc = mem_gc_get_ctx(mgc);
189 PCUT_ASSERT_NOT_NULL(gc);
190
191 /* Create bitmap */
192
193 params.rect.p0.x = 0;
194 params.rect.p0.y = 0;
195 params.rect.p1.x = 6;
196 params.rect.p1.y = 6;
197
198 /* TODO Test client allocation */
199 rc = gfx_bitmap_create(gc, &params, NULL, &bitmap);
200 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
201
202 rc = gfx_bitmap_get_alloc(bitmap, &balloc);
203 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
204
205 bpmap.width = params.rect.p1.x - params.rect.p0.x;
206 bpmap.height = params.rect.p1.y - params.rect.p0.y;
207 bpmap.data = balloc.pixels;
208
209 /* Fill bitmap pixels with constant color */
210 for (pos.y = params.rect.p0.y; pos.y < params.rect.p1.y; pos.y++) {
211 for (pos.x = params.rect.p0.x; pos.x < params.rect.p1.x; pos.x++) {
212 pixelmap_put_pixel(&bpmap, pos.x, pos.y,
213 PIXEL(0, 255, 255, 0));
214 }
215 }
216
217 dpmap.width = rect.p1.x - rect.p0.x;
218 dpmap.height = rect.p1.y - rect.p0.y;
219 dpmap.data = alloc.pixels;
220
221 memset(&update, 0, sizeof(update));
222
223 /* Render the bitmap */
224 /* TODO Test rendering sub-rectangle */
225 /* TODO Test rendering with offset */
226 rc = gfx_bitmap_render(bitmap, NULL, NULL);
227 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
228
229 /* Check that the pixels of the rectangle are set and no others are */
230 for (pos.y = rect.p0.y; pos.y < rect.p1.y; pos.y++) {
231 for (pos.x = rect.p0.x; pos.x < rect.p1.x; pos.x++) {
232 pixel = pixelmap_get_pixel(&dpmap, pos.x, pos.y);
233 expected = gfx_pix_inside_rect(&pos, &params.rect) ?
234 PIXEL(0, 255, 255, 0) : PIXEL(0, 0, 0, 0);
235 PCUT_ASSERT_INT_EQUALS(expected, pixel);
236 }
237 }
238
239 /* Check that the update rect is equal to the filled rect */
240 PCUT_ASSERT_TRUE(update.update_called);
241 PCUT_ASSERT_INT_EQUALS(params.rect.p0.x, update.rect.p0.x);
242 PCUT_ASSERT_INT_EQUALS(params.rect.p0.y, update.rect.p0.y);
243 PCUT_ASSERT_INT_EQUALS(params.rect.p1.x, update.rect.p1.x);
244 PCUT_ASSERT_INT_EQUALS(params.rect.p1.y, update.rect.p1.y);
245
246 /* TODO: Check clipping once memgc can support pitch != width etc. */
247
248 mem_gc_delete(mgc);
249 free(alloc.pixels);
250}
251
252/** Called by memory GC when a rectangle is updated. */
253static void test_update_rect(void *arg, gfx_rect_t *rect)
254{
255 test_update_t *update = (test_update_t *)arg;
256
257 update->update_called = true;
258 update->rect = *rect;
259}
260
261PCUT_EXPORT(memgfx);
Note: See TracBrowser for help on using the repository browser.