[과제] 3주차) ThorVG 활용사례 조사 이효진 #147
jinlee0310
started this conversation in
Blog
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
TinyPiXOS 조사
1. TinyPiXOS란
TinyPiXOS는 중국에서 개발된 오픈소스 경량 임베디드 데스크톱 OS다. 산업용 터치스크린, 의료기기 HMI 등을 타깃으로 하며, 가장 큰 특징은 X11/Wayland 그래픽 스택을 완전히 배제하고 순수 C/C++로 엔드투엔드 그래픽 스택을 재구축했다는 점이다. 구성은 다음과 같다.
TpWidget,TpPainter, signal-slot)이 중 TpGUI의 모든 픽셀은 ThorVG가 그린다. Cairo나 Skia 같은 별도 2D 라이브러리 없이, 도형·텍스트·이미지·이펙트·애니메이션 전부를 ThorVG 단일 엔진으로 처리하는, "ThorVG를 GUI 프레임워크의 유일한 래스터라이저로 채택한" 드문 사례다.
2. 빌드 통합 방식 — 서브모듈 + 정적 링크
TinyPiXOS는 ThorVG를 git 서브모듈로 가져와 정적 라이브러리로 빌드해 넣는다.
deps.mk의 빌드 레시피를 보면 ThorVG의 어떤 기능을 켜서 쓰는지 정확히 알 수 있다.주목할 점:
-Dloaders="all"— SVG, Lottie, PNG, JPG, WebP 로더를 전부 활성화. TpGUI의 이미지 시스템이 ThorVG 로더에 전적으로 의존하기 때문이다 (후술).-Dengines="sw,gl"— SW 래스터라이저를 기본으로 쓰되, GL 백엔드도 빌드해 둔다. 실제 코드에는USE_OPENGL매크로로tvg::GlCanvas전환 경로가 준비되어 있다 (아직 실험 단계, 주석으로 "暂时无用/당분간 미사용" 표기).libthorvg.a와 헤더(thorvg.h)를 트리 내부(src/include_p/TpGUI/thorVG/)로 복사해 TpGUI에 직접 임베드한다. 헤더가 저장소에 커밋되어 있어 TpGUI 소스 어디서든#include "thorVG/thorvg.h"로 접근한다.포크 저장소(
TinyPiXOS/thorvg)를 업스트림과 비교(gh api repos/thorvg/thorvg/compare/main...TinyPiXOS:thorvg:main)해 보면 ahead 0 / behind 392 — 즉 자체 패치 없이 업스트림 v1.0 개발 라인의 스냅샷을 미러링해 버전만 고정(pinning)해서 쓰고 있다. ThorVG의 공개 API만으로 OS급 GUI 스택을 구성할 수 있었다는 뜻이기도 하다.3. 핵심 아키텍처 — 위젯 트리를 ThorVG Scene 트리로 1:1 미러링
TinyPiXOS 통합의 가장 흥미로운 설계는 리테인드 모드(retained-mode) Scene 그래프 활용이다. Qt의 QPainter가 매 프레임 즉시 모드(immediate-mode)로 픽셀을 찍는 것과 달리, TpGUI는 위젯 계층 구조 자체를 ThorVG의
tvg::Scene트리로 그대로 미러링한다.3.1 위젯마다 Scene 하나
모든
TpWidget은 생성 시 자신의tvg::Scene을 소유한다.부모-자식 관계가 맺어지면 Scene도 부모 Scene에 push되어 트리를 형성한다.
위젯의 이동/클리핑도 픽셀 연산이 아니라 Scene 변환으로 처리된다.
즉 위젯 트리 = Scene 트리이며, 레이아웃 변경·투명도·클리핑·표시 여부가 전부 ThorVG의 Scene 속성으로 위임된다.
3.2 화면(Screen)마다 SwCanvas 하나, 타깃은 윈도우 매니저의 공유 버퍼
최상위
TpScreen이tvg::SwCanvas를 소유하고, 루트 Scene을 캔버스에 push한다.두 가지가 핵심이다.
Initializer::init(cores / 2)— ThorVG 내부 태스크 스케줄러에 CPU 코어의 절반을 할당. 임베디드 환경에서 UI 렌더링이 앱 로직과 코어를 나눠 쓰도록 한 균형점이다.EngineOption::SmartRender— ThorVG v1.0의 부분 렌더링(dirty region) 최적화를 활성화. 리테인드 Scene 구조와 결합하면, 프레임마다 변경된 Paint의 바운딩 영역만 다시 래스터라이즈된다. GPU 없는 산업용 보드에서 전체 화면 리드로우를 피하는 결정적 최적화다.캔버스의 출력 대상은 TpWM 윈도우 매니저가 관리하는 공유 메모리 서피스다. 리사이즈 시점에 바인딩된다.
ThorVG가 윈도우 매니저의 버퍼에 직접 그리므로, 중간 블리팅(blit) 단계나 별도 프레임버퍼 복사가 없다. "X11/Wayland 없이 초경량 스택"이라는 TinyPiXOS의 주장에서 ThorVG가 사실상 컴포지터 직전 단계까지 담당하는 셈이다.
3.3 프레임 파이프라인 — update()에서 픽셀까지
전체 흐름을 코드로 추적하면 다음과 같다.
DownUpdateCommand(src/include_p/TpGUI/GUI/TpApp_p.h)가 프레임의 심장이다.여러 위젯이 같은 프레임에 update()를 호출해도 사각형이 병합되고
draw()/sync()는 화면당 한 번만 실행된다. ThorVG의 비동기 렌더링 모델(draw()는 태스크 디스패치,sync()는 완료 대기)을 프레임 경계에 정확히 맞춰 쓰는 교과서적 사용법이다.drawWidget의 재귀 구조도 눈여겨볼 만하다.Scene::remove()로 이전 프레임의 Paint들을 비우고 위젯의onPaintEvent가 새로 채운다 — 위젯 단위로는 즉시 모드처럼 쓰되, 트리 전체는 리테인드로 유지하는 하이브리드다.tvg::SceneEffect::GaussianBlur로 직결된다. TpGUI의TpGraphicsBlurEffectAPI는 ThorVG SceneEffect의 얇은 래퍼이며,TpPainter::paintTest에는 배경 Scene에 블러를 걸어 만드는 글래스모피즘(유리 패널) 실험 코드도 있다 — 임베디드 GUI에서 SceneEffect로 iOS풍 프로스티드 글래스를 구현하려는 시도다.4. 아키텍처 다이어그램
5. 기술적 인사이트 정리
① ThorVG를 "벡터 뷰어"가 아니라 "GUI 렌더링 커널"로 쓴 사례.
대부분의 ThorVG 도입 사례(LVGL, dotLottie 등)는 기존 렌더러 옆에 Lottie/SVG 재생기를 붙이는 형태다. TinyPiXOS는 반대로 도형·텍스트·이미지·이펙트·애니메이션·윈도우 합성 직전 단계까지 전부 ThorVG 하나로 수렴시켰다.
TpPainterData에 다른 래스터라이저가 아예 존재하지 않는다.② 리테인드 Scene 그래프 + SmartRender의 시너지.
위젯 트리를 Scene 트리로 미러링했기 때문에, 위젯 하나가 바뀌면 해당 Scene만 재구성되고
EngineOption::SmartRender가 그 영역만 다시 그린다. 더티 렉트 병합(TpGUI 계층) + 부분 래스터라이즈(ThorVG 계층) + 부분 합성(TpWM 계층)의 3단 부분 갱신 파이프라인이 GPU 없는 보드에서 데스크톱급 UI를 성립시키는 핵심이다.③ 업스트림 무수정 사용.
포크는 버전 고정용 미러일 뿐(ahead 0), 커스텀 패치가 없다. OS 렌더링 코어라는 극한 용례에서도 ThorVG 공개 API(Scene/Shape/Text/Picture/Animation/SceneEffect)만으로 충분했다는 것은 API 설계 완성도에 대한 실전 방증이다.
복습용 요약
용어 미니 사전
EngineOption::SmartRender). 변경된 Paint의 바운딩 영역만 재래스터라이즈. TinyPiXOS는 이걸 켜서 쓰는 쪽wl_shm과 같은 아이디어draw()/sync()All reactions