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

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

Make display service argument optional

  • Property mode set to 100644
File size: 13.1 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/** @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/** Render circle to a bitmap.
218 *
219 * @param bitmap Bitmap
220 * @param w Bitmap width
221 * @param h Bitmap height
222 * @return EOK on success or an error code
223 */
224static errno_t bitmap_circle(gfx_bitmap_t *bitmap, gfx_coord_t w, gfx_coord_t h)
225{
226 int i, j;
227 int k;
228 pixelmap_t pixelmap;
229 gfx_bitmap_alloc_t alloc;
230 errno_t rc;
231
232 rc = gfx_bitmap_get_alloc(bitmap, &alloc);
233 if (rc != EOK)
234 return rc;
235
236 /* In absence of anything else, use pixelmap */
237 pixelmap.width = w;
238 pixelmap.height = h;
239 pixelmap.data = alloc.pixels;
240
241 for (i = 0; i < w; i++) {
242 for (j = 0; j < h; j++) {
243 k = i * i + j * j;
244 pixelmap_put_pixel(&pixelmap, i, j,
245 k < w * w / 2 ? PIXEL(255, 0, 255, 0) :
246 PIXEL(0, 255, 0, 255));
247 }
248 }
249
250 return EOK;
251}
252
253/** Run bitmap demo on a graphic context.
254 *
255 * @param gc Graphic context
256 * @param w Width
257 * @param h Height
258 */
259static errno_t demo_bitmap(gfx_context_t *gc, gfx_coord_t w, gfx_coord_t h)
260{
261 gfx_bitmap_t *bitmap;
262 gfx_bitmap_params_t params;
263 int i, j;
264 gfx_coord2_t offs;
265 gfx_rect_t srect;
266 errno_t rc;
267
268 rc = clear_scr(gc, w, h);
269 if (rc != EOK)
270 return rc;
271
272 gfx_bitmap_params_init(&params);
273 params.rect.p0.x = 0;
274 params.rect.p0.y = 0;
275 params.rect.p1.x = w;
276 params.rect.p1.y = h;
277
278 rc = gfx_bitmap_create(gc, &params, NULL, &bitmap);
279 if (rc != EOK)
280 return rc;
281
282 rc = bitmap_tartan(bitmap, w, h);
283 if (rc != EOK)
284 goto error;
285
286 for (j = 0; j < 10; j++) {
287 for (i = 0; i < 5; i++) {
288 srect.p0.x = rand() % (w - 40);
289 srect.p0.y = rand() % (h - 20);
290 srect.p1.x = srect.p0.x + rand() % (w - srect.p0.x);
291 srect.p1.y = srect.p0.y + rand() % (h - srect.p0.y);
292 offs.x = 0;
293 offs.y = 0;
294
295 rc = gfx_bitmap_render(bitmap, &srect, &offs);
296 if (rc != EOK)
297 goto error;
298 fibril_usleep(250 * 1000);
299
300 if (quit)
301 break;
302 }
303 }
304
305 gfx_bitmap_destroy(bitmap);
306
307 return EOK;
308error:
309 gfx_bitmap_destroy(bitmap);
310 return rc;
311}
312
313/** Run second bitmap demo on a graphic context.
314 *
315 * @param gc Graphic context
316 * @param w Width
317 * @param h Height
318 */
319static errno_t demo_bitmap2(gfx_context_t *gc, gfx_coord_t w, gfx_coord_t h)
320{
321 gfx_bitmap_t *bitmap;
322 gfx_bitmap_params_t params;
323 int i, j;
324 gfx_coord2_t offs;
325 errno_t rc;
326
327 rc = clear_scr(gc, w, h);
328 if (rc != EOK)
329 return rc;
330
331 gfx_bitmap_params_init(&params);
332 params.rect.p0.x = 0;
333 params.rect.p0.y = 0;
334 params.rect.p1.x = 40;
335 params.rect.p1.y = 20;
336
337 rc = gfx_bitmap_create(gc, &params, NULL, &bitmap);
338 if (rc != EOK)
339 return rc;
340
341 rc = bitmap_moire(bitmap, 40, 20);
342 if (rc != EOK)
343 goto error;
344
345 for (j = 0; j < 10; j++) {
346 for (i = 0; i < 10; i++) {
347 offs.x = rand() % (w - 40);
348 offs.y = rand() % (h - 20);
349
350 rc = gfx_bitmap_render(bitmap, NULL, &offs);
351 if (rc != EOK)
352 goto error;
353 }
354
355 fibril_usleep(500 * 1000);
356
357 if (quit)
358 break;
359 }
360
361 gfx_bitmap_destroy(bitmap);
362
363 return EOK;
364error:
365 gfx_bitmap_destroy(bitmap);
366 return rc;
367}
368/** Run bitmap color key demo on a graphic context.
369 *
370 * @param gc Graphic context
371 * @param w Width
372 * @param h Height
373 */
374static errno_t demo_bitmap_kc(gfx_context_t *gc, gfx_coord_t w, gfx_coord_t h)
375{
376 gfx_bitmap_t *bitmap;
377 gfx_bitmap_params_t params;
378 int i, j;
379 gfx_coord2_t offs;
380 errno_t rc;
381
382 rc = clear_scr(gc, w, h);
383 if (rc != EOK)
384 return rc;
385
386 gfx_bitmap_params_init(&params);
387 params.rect.p0.x = 0;
388 params.rect.p0.y = 0;
389 params.rect.p1.x = 40;
390 params.rect.p1.y = 40;
391 params.flags = bmpf_color_key;
392 params.key_color = PIXEL(0, 255, 0, 255);
393
394 rc = gfx_bitmap_create(gc, &params, NULL, &bitmap);
395 if (rc != EOK)
396 return rc;
397
398 rc = bitmap_circle(bitmap, 40, 40);
399 if (rc != EOK)
400 goto error;
401
402 for (j = 0; j < 10; j++) {
403 for (i = 0; i < 10; i++) {
404 offs.x = j * 20 + i * 20;
405 offs.y = i * 20;
406
407 rc = gfx_bitmap_render(bitmap, NULL, &offs);
408 if (rc != EOK)
409 goto error;
410 }
411
412 fibril_usleep(500 * 1000);
413
414 if (quit)
415 break;
416 }
417
418 gfx_bitmap_destroy(bitmap);
419
420 return EOK;
421error:
422 gfx_bitmap_destroy(bitmap);
423 return rc;
424}
425
426/** Run demo loop on a graphic context.
427 *
428 * @param gc Graphic context
429 * @param w Width
430 * @param h Height
431 */
432static errno_t demo_loop(gfx_context_t *gc, gfx_coord_t w, gfx_coord_t h)
433{
434 errno_t rc;
435
436 while (!quit) {
437 rc = demo_rects(gc, w, h);
438 if (rc != EOK)
439 return rc;
440
441 rc = demo_bitmap(gc, w, h);
442 if (rc != EOK)
443 return rc;
444
445 rc = demo_bitmap2(gc, w, h);
446 if (rc != EOK)
447 return rc;
448
449 rc = demo_bitmap_kc(gc, w, h);
450 if (rc != EOK)
451 return rc;
452 }
453
454 return EOK;
455}
456
457/** Run demo on console. */
458static errno_t demo_console(void)
459{
460 console_ctrl_t *con = NULL;
461 console_gc_t *cgc = NULL;
462 gfx_context_t *gc;
463 errno_t rc;
464
465 printf("Init console..\n");
466 con = console_init(stdin, stdout);
467 if (con == NULL)
468 return EIO;
469
470 printf("Create console GC\n");
471 rc = console_gc_create(con, stdout, &cgc);
472 if (rc != EOK)
473 return rc;
474
475 gc = console_gc_get_ctx(cgc);
476
477 rc = demo_loop(gc, 80, 25);
478 if (rc != EOK)
479 return rc;
480
481 rc = console_gc_delete(cgc);
482 if (rc != EOK)
483 return rc;
484
485 return EOK;
486}
487
488/** Run demo on canvas. */
489static errno_t demo_canvas(const char *display_svc)
490{
491 canvas_gc_t *cgc = NULL;
492 gfx_context_t *gc;
493 window_t *window = NULL;
494 pixel_t *pixbuf = NULL;
495 surface_t *surface = NULL;
496 canvas_t *canvas = NULL;
497 gfx_coord_t vw, vh;
498 errno_t rc;
499
500 printf("Init canvas..\n");
501
502 window = window_open(display_svc, NULL,
503 WINDOW_MAIN | WINDOW_DECORATED, "GFX Demo");
504 if (window == NULL) {
505 printf("Error creating window.\n");
506 return -1;
507 }
508
509 vw = 400;
510 vh = 300;
511
512 pixbuf = calloc(vw * vh, sizeof(pixel_t));
513 if (pixbuf == NULL) {
514 printf("Error allocating memory for pixel buffer.\n");
515 return ENOMEM;
516 }
517
518 surface = surface_create(vw, vh, pixbuf, 0);
519 if (surface == NULL) {
520 printf("Error creating surface.\n");
521 return EIO;
522 }
523
524 canvas = create_canvas(window_root(window), NULL, vw, vh,
525 surface);
526 if (canvas == NULL) {
527 printf("Error creating canvas.\n");
528 return EIO;
529 }
530
531 window_resize(window, 0, 0, vw + 10, vh + 30, WINDOW_PLACEMENT_ANY);
532 window_exec(window);
533
534 printf("Create canvas GC\n");
535 rc = canvas_gc_create(canvas, surface, &cgc);
536 if (rc != EOK)
537 return rc;
538
539 gc = canvas_gc_get_ctx(cgc);
540
541 task_retval(0);
542
543 rc = demo_loop(gc, 400, 300);
544 if (rc != EOK)
545 return rc;
546
547 rc = canvas_gc_delete(cgc);
548 if (rc != EOK)
549 return rc;
550
551 return EOK;
552}
553
554/** Run demo on display server. */
555static errno_t demo_display(const char *display_svc)
556{
557 display_t *display = NULL;
558 gfx_context_t *gc;
559 display_wnd_params_t params;
560 display_window_t *window = NULL;
561 errno_t rc;
562
563 printf("Init display..\n");
564
565 rc = display_open(display_svc, &display);
566 if (rc != EOK) {
567 printf("Error opening display.\n");
568 return rc;
569 }
570
571 display_wnd_params_init(&params);
572 params.rect.p0.x = 0;
573 params.rect.p0.y = 0;
574 params.rect.p1.x = 400;
575 params.rect.p1.y = 300;
576
577 rc = display_window_create(display, &params, &wnd_cb, NULL, &window);
578 if (rc != EOK) {
579 printf("Error creating window.\n");
580 return rc;
581 }
582
583 rc = display_window_get_gc(window, &gc);
584 if (rc != EOK) {
585 printf("Error getting graphics context.\n");
586 return rc;
587 }
588
589 task_retval(0);
590
591 rc = demo_loop(gc, 400, 300);
592 if (rc != EOK)
593 return rc;
594
595 rc = gfx_context_delete(gc);
596 if (rc != EOK)
597 return rc;
598
599 display_window_destroy(window);
600 display_close(display);
601
602 return EOK;
603}
604
605static void wnd_close_event(void *arg)
606{
607 printf("Close event\n");
608 quit = true;
609}
610
611static void wnd_kbd_event(void *arg, kbd_event_t *event)
612{
613 printf("Keyboard event type=%d key=%d\n", event->type, event->key);
614 if (event->type == KEY_PRESS)
615 quit = true;
616}
617
618static void print_syntax(void)
619{
620 printf("Syntax: gfxdemo [-d <display>] {canvas|console|display}\n");
621}
622
623int main(int argc, char *argv[])
624{
625 errno_t rc;
626 const char *display_svc = DISPLAY_DEFAULT;
627 int i;
628
629 i = 1;
630 while (i < argc && argv[i][0] == '-') {
631 if (str_cmp(argv[i], "-d") == 0) {
632 ++i;
633 if (i >= argc) {
634 printf("Argument missing.\n");
635 print_syntax();
636 return 1;
637 }
638
639 display_svc = argv[i++];
640 } else {
641 printf("Invalid option '%s'.\n", argv[i]);
642 print_syntax();
643 return 1;
644 }
645 }
646
647 if (i >= argc || str_cmp(argv[i], "display") == 0) {
648 rc = demo_display(display_svc);
649 if (rc != EOK)
650 return 1;
651 } else if (str_cmp(argv[i], "console") == 0) {
652 rc = demo_console();
653 if (rc != EOK)
654 return 1;
655 } else if (str_cmp(argv[i], "canvas") == 0) {
656 rc = demo_canvas(display_svc);
657 if (rc != EOK)
658 return 1;
659 } else {
660 print_syntax();
661 return 1;
662 }
663}
664
665/** @}
666 */
Note: See TracBrowser for help on using the repository browser.