source: mainline/uspace/app/gfxdemo/gfxdemo.c@ e49b7997

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

Avoid race between closing display and getting events

  • Property mode set to 100644
File size: 10.9 KB
Line 
1/*
2 * Copyright (c) 2019 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/** @addtogroup gfxdemo
30 * @{
31 */
32/** @file Graphic demo
33 */
34
35#include <canvas.h>
36#include <congfx/console.h>
37#include <draw/surface.h>
38#include <display.h>
39#include <fibril.h>
40#include <guigfx/canvas.h>
41#include <gfx/bitmap.h>
42#include <gfx/color.h>
43#include <gfx/render.h>
44#include <io/console.h>
45#include <io/pixelmap.h>
46#include <stdbool.h>
47#include <stdlib.h>
48#include <str.h>
49#include <task.h>
50#include <window.h>
51
52static void wnd_close_event(void *);
53static void wnd_kbd_event(void *, kbd_event_t *);
54
55static display_wnd_cb_t wnd_cb = {
56 .close_event = wnd_close_event,
57 .kbd_event = wnd_kbd_event
58};
59
60static bool quit = false;
61
62/** Clear screen.
63 *
64 * @param gc Graphic context
65 * @param w Screen width
66 * @param h Screen height
67 */
68static errno_t clear_scr(gfx_context_t *gc, gfx_coord_t w, gfx_coord_t h)
69{
70 gfx_color_t *color = NULL;
71 gfx_rect_t rect;
72 errno_t rc;
73
74 rc = gfx_color_new_rgb_i16(0, 0, 0, &color);
75 if (rc != EOK)
76 goto error;
77
78 rc = gfx_set_color(gc, color);
79 if (rc != EOK)
80 goto error;
81
82 rect.p0.x = 0;
83 rect.p0.y = 0;
84 rect.p1.x = w;
85 rect.p1.y = h;
86
87 rc = gfx_fill_rect(gc, &rect);
88 if (rc != EOK)
89 goto error;
90
91 gfx_color_delete(color);
92 return EOK;
93error:
94 if (color != NULL)
95 gfx_color_delete(color);
96 return rc;
97}
98
99/** Run rectangle demo on a graphic context.
100 *
101 * @param gc Graphic context
102 * @param w Width
103 * @param h Height
104 */
105static errno_t demo_rects(gfx_context_t *gc, gfx_coord_t w, gfx_coord_t h)
106{
107 gfx_color_t *color = NULL;
108 gfx_rect_t rect;
109 int i, j;
110 errno_t rc;
111
112 rc = clear_scr(gc, w, h);
113 if (rc != EOK)
114 return rc;
115
116 for (j = 0; j < 10; j++) {
117 rc = gfx_color_new_rgb_i16(rand() % 0x10000, rand() % 0x10000,
118 rand() % 0x10000, &color);
119 if (rc != EOK)
120 return rc;
121
122 rc = gfx_set_color(gc, color);
123 if (rc != EOK)
124 return rc;
125
126 for (i = 0; i < 10; i++) {
127 rect.p0.x = rand() % (w - 1);
128 rect.p0.y = rand() % (h - 1);
129 rect.p1.x = rect.p0.x + rand() % (w - 1 - rect.p0.x);
130 rect.p1.y = rect.p0.y + rand() % (h - 1 - rect.p0.y);
131
132 rc = gfx_fill_rect(gc, &rect);
133 if (rc != EOK)
134 return rc;
135 }
136
137 gfx_color_delete(color);
138
139 fibril_usleep(500 * 1000);
140
141 if (quit)
142 break;
143 }
144
145 return EOK;
146}
147
148/** Fill bitmap with tartan pattern.
149 *
150 * @param bitmap Bitmap
151 * @param w Bitmap width
152 * @param h Bitmap height
153 * @return EOK on success or an error code
154 */
155static errno_t bitmap_tartan(gfx_bitmap_t *bitmap, gfx_coord_t w, gfx_coord_t h)
156{
157 int i, j;
158 pixelmap_t pixelmap;
159 gfx_bitmap_alloc_t alloc;
160 errno_t rc;
161
162 rc = gfx_bitmap_get_alloc(bitmap, &alloc);
163 if (rc != EOK)
164 return rc;
165
166 /* In absence of anything else, use pixelmap */
167 pixelmap.width = w;
168 pixelmap.height = h;
169 pixelmap.data = alloc.pixels;
170
171 for (i = 0; i < w; i++) {
172 for (j = 0; j < h; j++) {
173 pixelmap_put_pixel(&pixelmap, i, j,
174 PIXEL(255, (i % 30) < 3 ? 255 : 0,
175 (j % 30) < 3 ? 255 : 0, i / 2));
176 }
177 }
178
179 return EOK;
180}
181
182/** Fill bitmap with moire pattern.
183 *
184 * @param bitmap Bitmap
185 * @param w Bitmap width
186 * @param h Bitmap height
187 * @return EOK on success or an error code
188 */
189static errno_t bitmap_moire(gfx_bitmap_t *bitmap, gfx_coord_t w, gfx_coord_t h)
190{
191 int i, j;
192 int k;
193 pixelmap_t pixelmap;
194 gfx_bitmap_alloc_t alloc;
195 errno_t rc;
196
197 rc = gfx_bitmap_get_alloc(bitmap, &alloc);
198 if (rc != EOK)
199 return rc;
200
201 /* In absence of anything else, use pixelmap */
202 pixelmap.width = w;
203 pixelmap.height = h;
204 pixelmap.data = alloc.pixels;
205
206 for (i = 0; i < w; i++) {
207 for (j = 0; j < h; j++) {
208 k = i * i + j * j;
209 pixelmap_put_pixel(&pixelmap, i, j,
210 PIXEL(255, k, k, k));
211 }
212 }
213
214 return EOK;
215}
216
217/** Run bitmap demo on a graphic context.
218 *
219 * @param gc Graphic context
220 * @param w Width
221 * @param h Height
222 */
223static errno_t demo_bitmap(gfx_context_t *gc, gfx_coord_t w, gfx_coord_t h)
224{
225 gfx_bitmap_t *bitmap;
226 gfx_bitmap_params_t params;
227 int i, j;
228 gfx_coord2_t offs;
229 gfx_rect_t srect;
230 errno_t rc;
231
232 rc = clear_scr(gc, w, h);
233 if (rc != EOK)
234 return rc;
235
236 gfx_bitmap_params_init(&params);
237 params.rect.p0.x = 0;
238 params.rect.p0.y = 0;
239 params.rect.p1.x = w;
240 params.rect.p1.y = h;
241
242 rc = gfx_bitmap_create(gc, &params, NULL, &bitmap);
243 if (rc != EOK)
244 return rc;
245
246 rc = bitmap_tartan(bitmap, w, h);
247 if (rc != EOK)
248 goto error;
249
250 for (j = 0; j < 10; j++) {
251 for (i = 0; i < 5; i++) {
252 srect.p0.x = rand() % (w - 40);
253 srect.p0.y = rand() % (h - 20);
254 srect.p1.x = srect.p0.x + rand() % (w - srect.p0.x);
255 srect.p1.y = srect.p0.y + rand() % (h - srect.p0.y);
256 offs.x = 0;
257 offs.y = 0;
258
259 rc = gfx_bitmap_render(bitmap, &srect, &offs);
260 if (rc != EOK)
261 goto error;
262 fibril_usleep(250 * 1000);
263
264 if (quit)
265 break;
266 }
267 }
268
269 gfx_bitmap_destroy(bitmap);
270
271 return EOK;
272error:
273 gfx_bitmap_destroy(bitmap);
274 return rc;
275}
276
277/** Run second bitmap demo on a graphic context.
278 *
279 * @param gc Graphic context
280 * @param w Width
281 * @param h Height
282 */
283static errno_t demo_bitmap2(gfx_context_t *gc, gfx_coord_t w, gfx_coord_t h)
284{
285 gfx_bitmap_t *bitmap;
286 gfx_bitmap_params_t params;
287 int i, j;
288 gfx_coord2_t offs;
289 errno_t rc;
290
291 rc = clear_scr(gc, w, h);
292 if (rc != EOK)
293 return rc;
294
295 params.rect.p0.x = 0;
296 params.rect.p0.y = 0;
297 params.rect.p1.x = 40;
298 params.rect.p1.y = 20;
299
300 rc = gfx_bitmap_create(gc, &params, NULL, &bitmap);
301 if (rc != EOK)
302 return rc;
303
304 rc = bitmap_moire(bitmap, 40, 20);
305 if (rc != EOK)
306 goto error;
307
308 for (j = 0; j < 10; j++) {
309 for (i = 0; i < 10; i++) {
310 offs.x = rand() % (w - 40);
311 offs.y = rand() % (h - 20);
312
313 rc = gfx_bitmap_render(bitmap, NULL, &offs);
314 if (rc != EOK)
315 goto error;
316 }
317
318 fibril_usleep(500 * 1000);
319
320 if (quit)
321 break;
322 }
323
324 gfx_bitmap_destroy(bitmap);
325
326 return EOK;
327error:
328 gfx_bitmap_destroy(bitmap);
329 return rc;
330}
331
332/** Run demo loop on a graphic context.
333 *
334 * @param gc Graphic context
335 * @param w Width
336 * @param h Height
337 */
338static errno_t demo_loop(gfx_context_t *gc, gfx_coord_t w, gfx_coord_t h)
339{
340 errno_t rc;
341
342 while (!quit) {
343 rc = demo_rects(gc, w, h);
344 if (rc != EOK)
345 return rc;
346
347 rc = demo_bitmap(gc, w, h);
348 if (rc != EOK)
349 return rc;
350
351 rc = demo_bitmap2(gc, w, h);
352 if (rc != EOK)
353 return rc;
354 }
355
356 return EOK;
357}
358
359/** Run demo on console. */
360static errno_t demo_console(void)
361{
362 console_ctrl_t *con = NULL;
363 console_gc_t *cgc = NULL;
364 gfx_context_t *gc;
365 errno_t rc;
366
367 printf("Init console..\n");
368 con = console_init(stdin, stdout);
369 if (con == NULL)
370 return EIO;
371
372 printf("Create console GC\n");
373 rc = console_gc_create(con, stdout, &cgc);
374 if (rc != EOK)
375 return rc;
376
377 gc = console_gc_get_ctx(cgc);
378
379 rc = demo_loop(gc, 80, 25);
380 if (rc != EOK)
381 return rc;
382
383 rc = console_gc_delete(cgc);
384 if (rc != EOK)
385 return rc;
386
387 return EOK;
388}
389
390/** Run demo on canvas. */
391static errno_t demo_canvas(void)
392{
393 canvas_gc_t *cgc = NULL;
394 gfx_context_t *gc;
395 window_t *window = NULL;
396 pixel_t *pixbuf = NULL;
397 surface_t *surface = NULL;
398 canvas_t *canvas = NULL;
399 gfx_coord_t vw, vh;
400 errno_t rc;
401
402 printf("Init canvas..\n");
403
404 window = window_open(DISPLAY_DEFAULT, NULL,
405 WINDOW_MAIN | WINDOW_DECORATED, "GFX Demo");
406 if (window == NULL) {
407 printf("Error creating window.\n");
408 return -1;
409 }
410
411 vw = 400;
412 vh = 300;
413
414 pixbuf = calloc(vw * vh, sizeof(pixel_t));
415 if (pixbuf == NULL) {
416 printf("Error allocating memory for pixel buffer.\n");
417 return ENOMEM;
418 }
419
420 surface = surface_create(vw, vh, pixbuf, 0);
421 if (surface == NULL) {
422 printf("Error creating surface.\n");
423 return EIO;
424 }
425
426 canvas = create_canvas(window_root(window), NULL, vw, vh,
427 surface);
428 if (canvas == NULL) {
429 printf("Error creating canvas.\n");
430 return EIO;
431 }
432
433 window_resize(window, 0, 0, vw + 10, vh + 30, WINDOW_PLACEMENT_ANY);
434 window_exec(window);
435
436 printf("Create canvas GC\n");
437 rc = canvas_gc_create(canvas, surface, &cgc);
438 if (rc != EOK)
439 return rc;
440
441 gc = canvas_gc_get_ctx(cgc);
442
443 task_retval(0);
444
445 rc = demo_loop(gc, 400, 300);
446 if (rc != EOK)
447 return rc;
448
449 rc = canvas_gc_delete(cgc);
450 if (rc != EOK)
451 return rc;
452
453 return EOK;
454}
455
456/** Run demo on display server. */
457static errno_t demo_display(void)
458{
459 display_t *display = NULL;
460 gfx_context_t *gc;
461 display_wnd_params_t params;
462 display_window_t *window = NULL;
463 errno_t rc;
464
465 printf("Init display..\n");
466
467 rc = display_open(DISPLAY_DEFAULT, &display);
468 if (rc != EOK) {
469 printf("Error opening display.\n");
470 return rc;
471 }
472
473 display_wnd_params_init(&params);
474 params.rect.p0.x = 0;
475 params.rect.p0.y = 0;
476 params.rect.p1.x = 400;
477 params.rect.p1.y = 300;
478
479 rc = display_window_create(display, &params, &wnd_cb, NULL, &window);
480 if (rc != EOK) {
481 printf("Error creating window.\n");
482 return rc;
483 }
484
485 rc = display_window_get_gc(window, &gc);
486 if (rc != EOK) {
487 printf("Error getting graphics context.\n");
488 return rc;
489 }
490
491 task_retval(0);
492
493 rc = demo_loop(gc, 400, 300);
494 if (rc != EOK)
495 return rc;
496
497 rc = gfx_context_delete(gc);
498 if (rc != EOK)
499 return rc;
500
501 display_window_destroy(window);
502 display_close(display);
503
504 return EOK;
505}
506
507static void wnd_close_event(void *arg)
508{
509 printf("Close event\n");
510 quit = true;
511}
512
513static void wnd_kbd_event(void *arg, kbd_event_t *event)
514{
515 printf("Keyboard event type=%d key=%d\n", event->type, event->key);
516 if (event->type == KEY_PRESS)
517 quit = true;
518}
519
520static void print_syntax(void)
521{
522 printf("syntax: gfxdemo {canvas|console|display}\n");
523}
524
525int main(int argc, char *argv[])
526{
527 errno_t rc;
528
529 if (argc < 2 || str_cmp(argv[1], "display") == 0) {
530 rc = demo_display();
531 if (rc != EOK)
532 return 1;
533 } else if (str_cmp(argv[1], "console") == 0) {
534 rc = demo_console();
535 if (rc != EOK)
536 return 1;
537 } else if (str_cmp(argv[1], "canvas") == 0) {
538 rc = demo_canvas();
539 if (rc != EOK)
540 return 1;
541 } else {
542 print_syntax();
543 return 1;
544 }
545}
546
547/** @}
548 */
Note: See TracBrowser for help on using the repository browser.