direct_draw.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. #include <furi.h>
  2. #include <gui/gui.h>
  3. #include <gui/canvas_i.h>
  4. #include <input/input.h>
  5. #define BUFFER_SIZE (32U)
  6. typedef struct {
  7. FuriPubSub* input;
  8. FuriPubSubSubscription* input_subscription;
  9. Gui* gui;
  10. Canvas* canvas;
  11. bool stop;
  12. uint32_t counter;
  13. } DirectDraw;
  14. static void gui_input_events_callback(const void* value, void* ctx) {
  15. furi_assert(value);
  16. furi_assert(ctx);
  17. DirectDraw* instance = ctx;
  18. const InputEvent* event = value;
  19. if(event->key == InputKeyBack && event->type == InputTypeShort) {
  20. instance->stop = true;
  21. }
  22. }
  23. static DirectDraw* direct_draw_alloc() {
  24. DirectDraw* instance = malloc(sizeof(DirectDraw));
  25. instance->input = furi_record_open(RECORD_INPUT_EVENTS);
  26. instance->gui = furi_record_open(RECORD_GUI);
  27. instance->canvas = gui_direct_draw_acquire(instance->gui);
  28. instance->input_subscription =
  29. furi_pubsub_subscribe(instance->input, gui_input_events_callback, instance);
  30. return instance;
  31. }
  32. static void direct_draw_free(DirectDraw* instance) {
  33. furi_pubsub_unsubscribe(instance->input, instance->input_subscription);
  34. instance->canvas = NULL;
  35. gui_direct_draw_release(instance->gui);
  36. furi_record_close(RECORD_GUI);
  37. furi_record_close(RECORD_INPUT_EVENTS);
  38. }
  39. static void direct_draw_block(Canvas* canvas, uint32_t size, uint32_t counter) {
  40. size += 16;
  41. uint8_t width = canvas_width(canvas) - size;
  42. uint8_t height = canvas_height(canvas) - size;
  43. uint8_t x = counter % width;
  44. if((counter / width) % 2) {
  45. x = width - x;
  46. }
  47. uint8_t y = counter % height;
  48. if((counter / height) % 2) {
  49. y = height - y;
  50. }
  51. canvas_draw_box(canvas, x, y, size, size);
  52. }
  53. static void direct_draw_run(DirectDraw* instance) {
  54. size_t start = DWT->CYCCNT;
  55. size_t counter = 0;
  56. float fps = 0;
  57. vTaskPrioritySet(furi_thread_get_current_id(), FuriThreadPriorityIdle);
  58. do {
  59. size_t elapsed = DWT->CYCCNT - start;
  60. char buffer[BUFFER_SIZE] = {0};
  61. if(elapsed >= 64000000) {
  62. fps = (float)counter / ((float)elapsed / 64000000.0f);
  63. start = DWT->CYCCNT;
  64. counter = 0;
  65. }
  66. snprintf(buffer, BUFFER_SIZE, "FPS: %.1f", (double)fps);
  67. canvas_reset(instance->canvas);
  68. canvas_set_color(instance->canvas, ColorXOR);
  69. direct_draw_block(instance->canvas, instance->counter % 16, instance->counter);
  70. direct_draw_block(instance->canvas, instance->counter * 2 % 16, instance->counter * 2);
  71. direct_draw_block(instance->canvas, instance->counter * 3 % 16, instance->counter * 3);
  72. direct_draw_block(instance->canvas, instance->counter * 4 % 16, instance->counter * 4);
  73. direct_draw_block(instance->canvas, instance->counter * 5 % 16, instance->counter * 5);
  74. canvas_draw_str(instance->canvas, 10, 10, buffer);
  75. canvas_commit(instance->canvas);
  76. counter++;
  77. instance->counter++;
  78. furi_thread_yield();
  79. } while(!instance->stop);
  80. }
  81. int32_t direct_draw_app(void* p) {
  82. UNUSED(p);
  83. DirectDraw* instance = direct_draw_alloc();
  84. direct_draw_run(instance);
  85. direct_draw_free(instance);
  86. return 0;
  87. }