|
| 1 | +# FPS: Полезная библиотека для вывода видео |
| 2 | + |
| 3 | +Из названия библиотеки (FPS -- «frame-per-second») следует, что её можно использовать для подсчёта кадров в секунду. Но она также имеет ряд функций, которые могут помочь Вам в работе с графическим выводом. |
| 4 | + |
| 5 | +## Интерфейс |
| 6 | + |
| 7 | +Название модуля -- `embox.lib.fps`, поэтому Вам следует или добавить `depends embox.lib.fps` в Ваш модуль «Mybuild», или явно вставить `include embox.lib.fps` в `conf/mods.conf` (хотя второй вариант использовать не рекомендуется). |
| 8 | + |
| 9 | +Заголовочный файл: `#include <fps/fps.h>`. |
| 10 | + |
| 11 | +## Основное применение |
| 12 | + |
| 13 | +Для начала убедитесь, что Вы знакомы с интерфейсом фрейм-буфера: [[Frame buffer]]. |
| 14 | + |
| 15 | +После того, как Вы получили `struct fb_info *`, Вы можете использовать FPS-библиотеку так же просто, как в следующем примере: |
| 16 | +```c |
| 17 | + struct fb_info *fbi = fb_lookup(0); |
| 18 | + fps_set_format("Hello, world!"); |
| 19 | + fps_print(fbi); |
| 20 | +``` |
| 21 | +
|
| 22 | +Теперь надпись `Hello, world!` должна появиться в левом верхнем углу экрана. Да, это не выглядит как что-то полезное, поэтому давайте выведем на экран фактическую скорость кадров в секунду: |
| 23 | +
|
| 24 | +```c |
| 25 | + struct fb_info *fbi = fb_lookup(0); |
| 26 | + /* Формат по умолчанию -- «Embox FPS=%d» */ |
| 27 | + fps_set_format("Hello, world!\nFPS=%d"); /* \n работает в случае с format string */ |
| 28 | + while(1) { |
| 29 | + fps_print(fbi); |
| 30 | + msleep(100); |
| 31 | + } |
| 32 | +``` |
| 33 | + |
| 34 | +Теперь на экране (на второй строчке) должна появиться надпись наподобие «FPS=10». |
| 35 | + |
| 36 | +## Двойная буферизация |
| 37 | + |
| 38 | +Иногда рендеринг сцены занимает много времени, поэтому, если мы отрисовываем сцену непосредственно на базе фрейм-буфера, на экране появятся помехи или т. н. глитчи. Двойная буферизация -- это метод, который позволяет решить эту проблему. |
| 39 | + |
| 40 | +Идея в том, чтобы хранить дополнительный буфер «back» для отрисовки, пока основной фрейм остаётся неизменным. |
| 41 | + |
| 42 | +Ниже представлен первый способ использования «back»-буфера: |
| 43 | +```c |
| 44 | +struct fb_info *fbi = fb_lookup(0); |
| 45 | + |
| 46 | +fps_enable_swap(fbi); |
| 47 | + |
| 48 | +while (1) { |
| 49 | + uint8_t *current_frame = fps_current_frame_fbi); |
| 50 | + draw_something(current_frame); |
| 51 | + fps_print(fbi); |
| 52 | + /* Переместить содержимое «back»-буфера на экран */ |
| 53 | + fps_swap(fbi); |
| 54 | +} |
| 55 | +``` |
| 56 | +
|
| 57 | +Способы могут быть более мудрёными, если Вы хотите, чтобы фрейм был помещён в определённую область памяти (например, если это специализированная память конкретного устройства для временного буфера). В этом случае Вы можете установить основу фрейма, используя следующие функции: |
| 58 | +
|
| 59 | +```c |
| 60 | + void fps_set_base_frame(struct fb_info *fb, void *base_frame); |
| 61 | + void fps_set_back_frame(struct fb_info *fb, void *base_back_frame); |
| 62 | +
|
| 63 | + /* Простой пример может выглядеть следующим образом */ |
| 64 | + struct fb_info *fbi = fb_lookup(0); |
| 65 | +
|
| 66 | + fps_set_base_frame(fbi, some_addr_1); |
| 67 | + fps_set_back_frame(fbi, some_addr_2); |
| 68 | +
|
| 69 | + while (1) { |
| 70 | + uint8_t *current_frame = fps_current_frame_fbi); |
| 71 | + draw_something(current_frame); |
| 72 | + fps_print(fbi); |
| 73 | +
|
| 74 | + /* Переместить содержимое «back»-буфера на экран */ |
| 75 | + fps_swap(fbi); |
| 76 | + } |
| 77 | +``` |
| 78 | + |
| 79 | +Обратите внимание: это будет корректно работать только в случае, если данное устройство вывода видео поддерживает изменение базы фрейм-буфера. В противном случае, будет работать только «простой» пример двойной буферизации. |
0 commit comments