ThorVG 활용사례 선정과 그 이유 (TinyPiXOS)
- 원래부터 컴파일러, 그래픽스 등 저수준의 시스템에 관심이 있어 TinyPiXOS를 선택하게 되었습니다.
- Wayland / X11 등을 배제하고 TpWM, TpGUI등 자체 그래픽 스택을 가지고 있습니다.
- Target machine은 ARM, RISC-V, x86 기반의 임베디드 기기 즉 리소스 제약이 강한 기계들을 target 했습니다.
- Goal은 최소한의 하드웨어 파워로 데스크톱급 멀티 앱 환경을 구현하는데 목표를 두고 하고 있습니다.
TinyPiXOS의 ThorVG 활용사례
- TpGUI라는 자체 그래픽 스택에 ThorVG가 프레임워크 전체의 유일한 백엔드 렌더러 입니다.
- 즉, 화면의 출력되는 모든 시각적 요소는 ThorVG의 Scene graph와 Rasterizer를 거칩니다.
Deep dive of ThorVG in TinyPiXOS
- ThorVG는 TinyPiXOS에서 git 서브 모듈로 포함 되어있습니다.
- 실제 deps.mk파일에서도 유일하게 meson을 이용해 static build 합니다.
- deps.mk (lines 78–91)
thorvg:
cd $(src_dir)/thorvg; \
meson setup builddir \
-Dbuildtype=release \
-Dloaders="all" -Dengines="sw,gl" \
-Dsavers="all" \
-Dexamples=false \
-Dlog=false \
--default-library=static \
--prefix=$(prefix)/thorvg \
--libdir=lib \
&& ninja -C builddir install; \
cp $(prefix)/thorvg/include/* $(core_root)/src/include_p/TpGUI/thorVG/; \
cp $(prefix)/thorvg/lib/libthorvg.a $(core_root)/src/depend_lib/static/$(libDir)/;
위젯 트리와 씬 그래프 1:1 매핑 (TpWidget.cpp)
모든 위젯은 tvg::Scene을 소유하며, 위젯의 부모-자식 관계가 ThorVG의 씬 그래프 계층 구조로 그대로 전달됩니다.
// src/include_p/TpGUI/GUI/TpWidget_p.h
struct TpWidgetData : TpObjectData {
tvg::Scene *tvgScene = nullptr; // 각 위젯이 ThorVG Scene을 소유
};
// TpWidget.cpp (자식 위젯 추가 시)
parentWidgetData->tvgScene->push(widgetData->tvgScene);
Zero-Copy 프레임버퍼 바인딩 및 렌더링 (TpScreen.cpp, TpApp_p.h)
ThorVG 캔버스를 창 관리자(TpWM)의 디스플레이 메모리에 직접 바인딩하여 복사 과정(Blit) 없이 즉시 렌더링합니다.
// 1. 디스플레이 메모리 직접 바인딩 (TpScreen.cpp)
screenData->swCanvas->target(
(uint32_t *)screenData->wmSurface->matrix(),
surfaceWidth, surfaceWidth, surfaceHeight,
tvg::ColorSpace::ARGB8888
);
// 2. 렌더링 파이프라인 구동 (TpApp_p.h)
topCanvas->update(); // 변경된 더티 영역 계산
topCanvas->draw(); // 프레임버퍼에 래스터라이제이션 수행
topCanvas->sync(); // 비동기 렌더링 스레드 완료 대기
이미지 렌더링 및 둥근 모서리 마스킹 (TpPainter.cpp)
이미지 객체 오염을 방지하기 위해 duplicate()로 복사한 뒤, ThorVG의 Alpha Mask를 적용해 둥근 모서리를 표현합니다.
// TpPainter.cpp (drawImage)
tvg::Picture *pictureCopy = static_cast<tvg::Picture *>(imageData->tvgPicture->duplicate());
pictureCopy->translate(point.x(), point.y());
if (roundRad != 0) {
auto clipper = tvg::Shape::gen();
clipper->appendRect(x, y, w, h, roundRad, roundRad);
clipper->fill(255, 255, 255, 255);
// Alpha 마스크를 통해 둥근 모서리 영역만 출력
pictureCopy->mask(clipper, tvg::MaskMethod::Alpha);
}
painterData->tvgScene->push(std::move(pictureCopy));
- 사례가 더 많으나 일단 제가 핵심적이라고 생각한 부분만 가져왔습니다.
아키텍쳐 다이어그램
- 정리를 위한 아키텍쳐 다이어 그램입니다
text와 mermaid가 깨져서 그림으로 대체하는점 양해 부탁드립니다
마치며
- TinyPiXOS 프로젝트에서 ThorVG는 그냥 외부 라이브러리가 아닌 TpGUI Framework 자체가 ThorVG의 Scene graph와 redering API를 추상화하도록 설계된 TpGUI 렌더링 백엔드 그 자체 입니다. (콜백 없음)
- TinyPiXOS의 목표인 x86, ARM, RISC-V 등 다양한 환경을 지원하는 크로스 컴파일 환경과 소프트웨어 래스터라이저 중심의 경량 구조를 지원하며 Lottie/SVG 등 최신 벡터 그래픽을 지원하는건 사실상 ThorVG가 유일합니다.
- 때문에 TinyPiXOS는 데스크톱 UI 환경을 저사양 임베디드 기기위에 구동 시키기 위해 X11 / Wayland를 버리고 ThorVG를 선택한것으로 보입니다.
댓글
Discussion 원문