Phase 3b: PNG icon overlays через libpng + alpha_blit_rgba_nv12

Live-validated на rtsp://192.168.88.23:554/cfc-grid с иконками
temp_outside.png и offline.png из cuda_grid_icons volume.

Содержимое:

- cugrid.h/cugrid.cu — cfc_cugrid_blit_rgba_nv12 (Y+UV α-blend) +
  два новых kernel'я blit_rgba_y/uv (BT.709 limited-range RGB→YUV
  conversion, 4:2:0 chroma 2x2 averaging).
- overlay.h — cfc_overlay_create_png + cfc_overlay_png_size +
  cfc_overlay_update_png.
- overlay.c — libpng decode (paletted/gray/16-bit → 8-bit RGBA),
  cuMemAlloc atlas в VRAM, cuMemcpyHtoD один раз, draw_png через
  cfc_cugrid_blit_rgba_nv12.
- CMakeLists.txt — find_package(PNG REQUIRED) + PNG::PNG в link.
- examples/grid_record — флаг --icon path,x,y[,alpha] (несколько раз
  можно). Атлас грузится один раз при старте.

PNG из cuda_grid_icons volume переиспользуются (offline, temp_outside,
grafana_gpu, и пр.). PNG decode'ятся одинаково — paletted, RGBA, gray.

Phase 3c (text rendering через FreeType + font atlas) — отдельный
commit. Атлас text'а тоже окажется в VRAM как RGBA через тот же
cfc_cugrid_blit_rgba_nv12 — kernels уже готовы.
This commit is contained in:
2026-06-03 05:34:07 +01:00
parent 87daff313e
commit 8cc5a5acfb
7 changed files with 366 additions and 3 deletions
+23
View File
@@ -51,6 +51,29 @@ int cfc_cugrid_fill_nv12(
int color_y, int color_u, int color_v, int alpha
);
/* Blit RGBA atlas → NV12 frame с α-blending.
*
* BT.709 limited-range conversion (R/G/B → Y/U/V). UV pixel = среднее 2x2
* пикселей RGBA (4:2:0 chroma subsampling).
*
* dst_y/uv, pitch_y/uv — NV12 destination.
* dst_x, dst_y_off — позиция top-left на dst (full-res, чётные).
* atlas — CUdeviceptr RGBA байт (4 байта/пиксель,
* R,G,B,A interleaved).
* atlas_w, atlas_h — размер atlas в пикселях.
* atlas_pitch — pitch atlas в байтах.
* extra_alpha — 0..255, общий множитель прозрачности (для
* анимаций fade-in/fade-out).
*/
int cfc_cugrid_blit_rgba_nv12(
CUstream stream,
CUdeviceptr dst_y, int dst_pitch_y,
CUdeviceptr dst_uv, int dst_pitch_uv,
int dst_x, int dst_y_off,
CUdeviceptr atlas, int atlas_w, int atlas_h, int atlas_pitch,
int extra_alpha
);
/* Resize NV12 src → rect (dst_x, dst_y, dst_w, dst_h) на NV12 dst.
*
* Bilinear interpolation на Y и UV. Y и UV plane src'а должны быть одним
+24
View File
@@ -60,6 +60,30 @@ typedef struct cfc_overlay_border_config {
int cfc_overlay_create_border(const cfc_overlay_border_config_t *cfg,
cfc_overlay_t **out);
/* Параметры PNG overlay'я. */
typedef struct cfc_overlay_png_config {
const char *path; /* путь к PNG-файлу (декод один раз) */
int x, y; /* позиция top-left на output буфере (чётные) */
int extra_alpha; /* 0..255 общий множитель прозрачности */
int visible; /* 0/1 — выводить ли */
} cfc_overlay_png_config_t;
/* Создать PNG overlay. Декодирует файл через libpng, аллоцирует RGBA-атлас
* в VRAM (cuMemAlloc), копирует туда декодированные пиксели один раз.
*
* Размер изображения берётся из PNG header'а — caller узнаёт width/height
* через cfc_overlay_png_size после create. */
int cfc_overlay_create_png(const cfc_overlay_png_config_t *cfg,
cfc_overlay_t **out);
/* Получить реальный размер декодированного PNG. После create — стабильны
* до destroy. */
int cfc_overlay_png_size(cfc_overlay_t *ov, int *width, int *height);
/* Обновить параметры PNG overlay'я (без re-decode). */
int cfc_overlay_update_png(cfc_overlay_t *ov,
const cfc_overlay_png_config_t *cfg);
/* Обновить параметры BORDER overlay'я (можно переключить visible,
* сменить цвет, изменить позицию). Thread-safe? Нет — caller должен сам
* заботиться о том, чтобы update не пересекался с draw. В рамках одного