[Study Note] Example 예제가 실제로 화면에 그려지기까지의 코드 흐름 추적하기. - 1 #28
jeongsunyong
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.
[Study Note] ThorVG 실행 흐름 분석 (1)
0. Overview
이 Study 주제의 목적은, 위 스크린 샷 처럼 Topdown 방식으로 Example의 SVG 파일 하나가 Picture로 들어와 CPU Renderer를 통해 화면에 그려지는 전체 Call Flow 설명하는 것을 목적으로 한다. (3~4회에 걸쳐 정리 예정)
빠른 basic flow 확인을 위해, 우선 하나의 단색 벡터 도형을 렌더링하기 위한 흐름을 최소 단위로 관찰하기 쉽도록 아래의 최소 client sample을 별도로 만들었다.
1. thorVG 라이브러리와 렌더링 엔진 overview
Paint,Shape,Scene,Picture,Text등 그래픽 객체 모델Canvas를 통한 Paint 관리와 렌더링 생명주기2. Example 구조 overview
thorvg.example: 라이브러리 사용자 관점에서의 샘플. ThorVG Core가 아니다. ThorVG를 사용하는 client이자 여러 기능을 같은 방식으로 실행하기 위한 example 이다.
main()과 애플리케이션 생명주기draw()결과를 화면에 표시여기까지 봤을 때에는, OS Window와 실행모드에 대한 권한이 client(example)단에 있어 thorVG의 관심사가 아닌 것으로 순간 생각이 들었는데,
Window 자체는 ThorVG의 관심사가 아니지만 애플리케이션이 Window의 그래픽 환경에 맞는 Canvas와 target을 선택해서 ThorVG에 제공하면, ThorVG는 그 이후 해당 backend에 맞는 실제 벡터 렌더링을 처리한다.
참고) Example implementation
Issue를 재현해보거나, 특정 동작 시나리오 확인을 위해서 example을 구성해야할 경우, 아래 정보를 참고할 수 있다.
Example.h의tvgexam::Example에 예제별 동작을 끼워 넣기 위한 인터페이스가 갖춰져있다.content()만 순수 가상 함수이므로 모든 예제는 최소한 Canvas에 무엇을 넣을 것인가를 반드시 정의해야 한다. 반면 animation이나 interaction이 필요하지 않은 예제는update(), mouse, keyboard hook을 override하지 않아도 된다.공통 실행부가 전체 생명주기를 소유하고 예제는 필요한 hook만 구현한다.
FrameRenderCallback이나 일반적인 OpenGL 프로그램의 RenderLoop와 유사하다.
contribution에서 디버그 포인트가 될 수 있는 것은 (by chatGPT)
content()호출 전 문제는 대개 example harness나 backend 초기화 문제이고,content()에서 구성한 Paint가 이후 잘못 렌더링되는 문제는 ThorVG Core까지 추적해야 하는 문제라고 함.3. Window
ThorVG는 OS Window toolkit이 아니라 렌더링 라이브러리다. ThorVG의 책임은 주어진 target에 그래픽 결과를 만드는 것이며, 화면 창과 이벤트 루프는 client가 준비해야 한다.
Software 경로에서
SwWindow는 SDL을 이용해 다음 외부 자원을 준비한다.역할은 다음과 같이 나뉜다.
SDL_WindowSDL_SurfaceSwCanvasSwCanvas::target()SDL_UpdateWindowSurface()즉, 화면 출력은 하나의 책임이 아니라 두 단계다.
이 구조 덕분에 ThorVG는 SDL에 종속되지 않는다. 다른 UI framework도 자체 버퍼나 GPU target을 Canvas에 연결할 수 있다.
4. 현재 환경 : SwCanvas
이는 ThorVG가 자동으로 하드웨어를 감지한 건 아니고 example 에 정의되어있다.
... if (engine == 0) { window = unique_ptr<Window>(new SwWindow(...)); } else if (engine == 1) { window = unique_ptr<Window>(new GlWindow(...)); } else if (engine == 2) { window = unique_ptr<Window>(new WgWindow(...)); } }현재 ThorVG는
engines=[cpu]이므로 Software는 동작하지만GlCanvas::gen()은 지원되지 않는다. 이는 client의 runtime 분기와 library의 compile-time feature 구성이 분리돼 있음을 보여준다.Canvas?
Canvas : drawing engine과 target buffer를 설정하고, 주어진 Paint 객체를 관리하는 추상 객체
client는
tvg::Canvas*를 사용하지만 실제 구현은 달라질 수 있다.Shape는 무엇을 그릴지를 표현하지만 어디에 그릴지는 알지 못한다. Canvas가 buffer 크기, stride, color space 또는 GPU target을 Renderer와 연결한다.
Canvas::add(Paint*)는 Paint를 root scene에 넣는다. 공개 계약에 따르면 추가 순서가 렌더링 순서가 되며, 성공하면 Paint의 ownership도 Canvas로 이전된다.Canvas는 State를 관리한다. (Paint 등록 변경 → update → draw → sync)
따라서 Shape를 Renderer에 직접 전달하면 client가 backend 선택, scene ordering, target 상태, 비동기 동기화까지 직접 관리해야 한다. Canvas는 이 책임들을 하나의 public API boundary로 묶는다.
5. Shape Example의 콘텐츠 구성에 사용된 ThorVG Public API
ThorVG의 Shape API는 벡터 그래픽을 구성하는 주요 요소인 geometry, fill, stroke같은 것들을 public interface로 제공한다.
아마 fill rule이라던지, path 그리는 cubic to라던지 line join 방식을 제공한다던지 아직 보진 않았지만 이런 그릴 수 있는 방법을 제공하고, 이것들을 이용해서 shape를 그린다.
Shape::gen()appendRect()fill()Canvas::add()Shape::gen()
ThorVG의
Paint는 추상 그래픽 요소이며 직접 생성할 수 없다. 사각형처럼 path 기반 벡터 기하를 표현하기 위해 구체 타입Shape를 선택한다.Picture는 파일/데이터 로딩,Text는 글리프,Scene은 Paint 그룹을 위한 타입이므로 이번 최소 입력에는 맞지 않는다.appendRect()
Shape의 핵심 속성 중 하나는 path다. 직접
moveTo/lineTo/close로 사각형을 만들 수도 있지만appendRect()는 같은 path를 더 명확하고 적은 호출로 만든다. Renderer 관점에서는 “사각형 객체”라기보다 Shape에 축적된 path 입력으로 이어지는지 이후 구현에서 확인해야 한다.fill()
기하만 있고 fill과 stroke가 모두 없다면 화면에 나타낼 색상 정보가 없다. 이번 study에서는 stroke와 gradient 분기를 제거하고 단색 fill 경로 하나만 남긴다.
Canvas::add()
Shape를 생성하고 속성을 설정하는 것만으로는 렌더링 대상이 아니다. Canvas의 root scene에 등록해야 이후 update/draw가 해당 Paint를 순회할 수 있다. 공개 API 계약상 성공한
add()는 ownership도 Canvas로 이전한다.이 네 호출은 다음 최소 파이프라인을 구성한다.
위 API들에서는 최종 픽셀을 직접 기록하지 않고, 실제 렌더링 요청은
Canvas::draw()에서 시작된다.6. 실제 제어 흐름
Example harness가 실행 환경과 target을 준비
→ client hook이 ThorVG 객체로 scene을 기술
→ Canvas가 scene을 Renderer에 실행하도록 요청
→ example harness가 결과 target을 화면에 present
의 제어 흐름을 따른다고 한다.
참고차. by chat GPT
7. Next
각 public api 호출이 변경하는 내부 상태를 추적
그 뒤
Canvas::draw()가 이 상태를 Software Renderer 입력으로 바꾸는 경계를 찾아 볼 것이다.All reactions