3강
(궁금했던 점: *로 표시. 해결된 부분: --로 *옆에 중첩해서 표시.)
(()) : 스터디시 질문에 대한 답변.
- EGL에 대한 이야기.
- 2강처럼 자체함수를 사용하면 개념 이해에는 용이할 수 있지만, 실제 opengl es 3.0으로
작업하기에는 어려울 수 있으므로 EGL을 사용해서 하나의 기능 구현하는 걸 예시로 보여줘서
EGL에 대해서 알아볼 것.
플랫폼별 다른 방식으로 opengl 윈도우 관리하지 않고 통합적으로 관리하기 위해 만들어진 것.
EGL : 장치의 native windowing system과 통신.
- 사용가능한 drawing surfaces의 유형을 및 구성 보여줌.
- drawing surfaces 만들어서 그래픽스 컨텍스트 연결.
- OpenGL ES 3.0과 같은 기타 그래픽 렌더링 API 간의 렌더링 동기화.
(OpenVG((1**--)하드웨어 가속 벡터 그래픽을 위한 것.) 기본 드로잉 명령)
-> egl: 크로노스 렌더링 api와 아래 단의 네이티브 플랫폼 윈도우 시스템 사이의 인터페이스.
(++용어정리
네이티브 플랫폼 윈도우 시스템: 디스플레이 스크린의 각 부분을 관리하는 sw
그래픽스 컨텍스트: 윈도우의 렌더링 데이터 저장하는 구조체.(각 윈도우들 구분 가능. 개별적 렌더링)
서피스: 이미지 렌더링을 위해 생성될 이미지를 저장하려고 할당된 메모리(이미지 버퍼)를 추상화한 것.
-> 추상화되어서 이미지 버퍼 자체를 신경쓰지 않고 관리 가능.
싱크로나이징 렌더링: opengl 렌더링 파이프라인에서 완전히 실행했는지 확인하는 프로세스.
)
1) hardware-accelerated vector graphics?
오픈 벡터 그래픽의 파이프라인을 하드웨어로 설계->벡터 그래픽 처리 수행 성능 증가,
소프트웨어 렌더링 처리에 사용하던 openvg 벡터 콘텐츠를 별도 변환 없이 사용하는 하드웨어 방식 벡터 그래픽 가속기.
EGL : 기본 window 시스템 - opengl es 3.0 사이에서 glue 레이어 제공.
(2**--) glue layer?-> 데이터 변환. 해당 디스플레이 형식에 맞게.
EGL이 사용 가능한 drawing surface/ 다른 기능 확인하려면 윈도우와의 통신 채널 열어야 함.
코드 돌아가는 과정
- 로컬 EGL 디스플레이와의 연결 생성 및 초기화.
(윈도잉 시스템은 다른 semantics를 가져서 윈도잉 시스템과의 인터페이스를 위해
모든 시스템 종속성을 캡슐화하는 EGLDisplay 제공.)
우선 로컬 윈도우 시스템과 연결할 수 있는지 확인하고, EGL 초기화 여부를 확인 후 진행합니다.
1.1 eglGetDisplay
장치 컨텍스트에 대한 핸들-HDC(마소 윈도우 기준)
((다양한 운체 윈도잉시스템 추상화.
default display: 기본 디스플레이.))
1.2 eglGetError()
해당 함수를 사용해 호출 실패 여부 및 이유를 리턴해줌.
특정 스레드에서 호출 완료된 가장 최근 EGL 함수의 오류 코드 반환.
(에러가 생길 때만 선택적으로 반환해서 제대로 작동하는 경우에 대해 에러 확인 횟수 줄일 수 있음.)
((언제 nodisplay? 데이터센터 들어가는 경우(CLI가 없어서) 에러냄.))
((매번 호출-runtime상에서 많이 하므로 에러 호출 줄이기. 최근 라이브러리는 다른 개념으로 더 접근.
이건 egl만의 특성.
cpp assault와 같은 것을 사용해 디버거는 에러체크, 릴리즈는 그냥 없애는 방식.
))
1.3 eglInitialize
EGL 디스플레이 연결 지정.
반환한 egl implementation 메이저 버전, 마이너 버전 번호 반환.
(3**메이저버전, 마이너 버전을 왜 2개나 반환하는 거지?)
((struct-값 복사, class는 레퍼런스로 감.(자바)
포인터이기 때문에 이렇게 사용함.
))
- egl 초기화 후 렌더링 표면의 유형/구성 결정. -> 사용할 메모리 크기 할당받는 과정+해당 메모리에 맞는 configs 가져옴.
이 방법
- 모든 surface configuration을 찾아서 최적의 configuration(4**--조건이라고 우당탕탕 해석) 찾기
- 요구사항 지정하고 egl에서 가장 잘 맞는 것을 찾는다.
2번째가 더 쉬움.
- egl은 특정 surface, 그 특성에 대한 정보 포함된 eglConfig반환.(각 컬러 컴포넌트 비트 수/해당 eglconfig와 연관된 depths buffer 있는 경우(5**-- 문장 이해)
eglGetConfigs
egl display 연결 지정, configs 지정, configs 크기 지정, 반환되는 구성 크기 지정.
호출 방법 2개.
(configs-null : 시스템은 egl-true, numconfigs를 사용가능한 eglconfigs 수로 지정.-> 컴퓨터가 임의로 이만큼 사용할 꺼라고 지정.)
(초기화되지 않은 eglconfig 값의 배열 할당하고 configs 파라미터로 eglGetConfigs에 전달 가능.
=> maxReturnConfigs를 할당된 배열 크기로 설정하면 반환되는 configs 최대 개수 지정가능. 호출하면 됨.
리턴된 값의 목록을 처리하기 시작해 필요에 따라 가장 적합한 config 결정. -> 유저가 임의로 지정해서 할 수 있음)
왜 이런 2가지 호출 방법이 있지? 그러면 두 번째는 최대개수를 지정한 후 그에 맞는 모든 configs들을 가져와서 내가 정하는건가?(6**--)
((고급과정에 들어가면 specific하게 더 원하는 걸 선택할 수 있는거지 일단 여기서는 디폴트로만 알려줌.
쿼리도 필요없음.
))
- Querying EGLConfig Attributes (eglconfig 설명 + 해당 값 검색)
eglconfig에서 원하는 attributes 검색하기.
display: egl connection 점검하기.
config: 쿼리할 configs들
attributes : 리턴할 attributes
value: 특정 값? (7**-- -> 잘 모름. egl 자체가 추상화된 인터페이스여서 크게 중요하지 않음.)
이 함수 옵션이 굉장히 많으므로 eglChooseconfig를 사용해서 가장 맞는 구성 반환.
(8**-- 요청에 가장 적합한 config라는 의미가 뭐지? 해당 윈도우 조건에 맞는/내가 렌더링할
조건에 맞는 버퍼 번호와 같은 것을 렌더링한다는 것)
(9** 적합한 config를 어떻게 알고 알려주는거지?-> 해당 버전+기기 조건 알고 있으니 그냥 조건에 맞게 출력하나?)
3-1. eglChoose ->
((best 조건 뽑아줌.
해당 조건 depts(rgb 565로 꼭 설정되는 건 아님.)
))
디스플레이 연결 지정
attribList: configs로 일치시킬 config 목록 지정.
configs: configs 목록 지정.
maxReturnConfigs: Configs 크기 지정.
numConfigs: 반환되는 Configs 크기 지정.
반환값 3가지.
올바른 작동에 중요한 모든 attributes에 대해 기본값, 속성 목록 제공.
(10**--egl_config_caveat : 경고값. 어떤 렌더링 방식인지 알려주는 것
20**-- egl_slow_config와 non-conformant_config 차이? )
성공적으로 반환시 그릴 수 있는 충분한 정보 얻음. 기본적으로 egl_surface_type 지정 안하면
사용자가 온스크린 창을 원한다고 가정.
- on-screen 렌더링할 부분 만들기
eglcreateWindowSurface 호출.
egl display 연결 지정
configuration 설정
nativewindowtype 설정
attribList: window attributes list 지정. null일 수도 있음.
(다른 렌더링 api를 지원해서 일부 속성 적용되지 않음.
렌더링할 프론트버퍼/백 버퍼 지정할 때 단일 attrib 사용.
((11** --왜 단일을 사용하지?
더블 버퍼링 레이턴시 늘어남.(지금 늘어난 게 다음 버퍼링에 나와서.)
vr-바로바로 반응성이 중요해서 반응성 하나만 씀. 화면 주사-내가 렌더링하는 거 타이밍이 맞게 나오는 게 중요해서 싱글 버퍼만 씀.
))
하나의 버퍼를 사용해서 더블 버퍼링 기법을 사용하므로 하나의 메모리 주소만 가져오면 되서 싱글을 쓰나 )
eglconfig + display connection argument로 받음.
해당 함수가 실패할 경우가 여러가지이므로 해당 경우를 확인하기 위해 EglGetError함수 이용.
- off-screen rendering을 위한 egl pbuffers
눈에 보이지 않는 off-screen surfaces로 렌더링 가능.
pbuffer: 텍스쳐 맵 생성에 주로 사용.
텍스쳐에 렌더링만 하는 경우는 다른 것을 써도 좋지만, 프레임버퍼오브젝트를 사용할 수 없는 경우는
pbuffer 유용.
(opengl es로 오프스크린 표면 렌더링 후 다른 api에서 텍스쳐로 사용? 이게 무슨 말이지?
13**이러면 텍스쳐맵 생성된 걸
다른 api에서 갔다 사용하는 케이스를 말하는건가?)
pbuffer은 egl_surface_type값 추가해야 함.
pbuffer에 맞는 코드 추가(14**--차이: 렌더링 완료되면 버퍼 교체가 아닌 버퍼값을
애플리케이션으로 복사하거나 버퍼의 바인딩 텍스쳐로 수정. 왜 버퍼값 복사하지?
double buffering을 안쓰나?
--> opengl은 싱글 스레드여서)
- Rendering Context 만들기
rendering context: 작동에 필요한 모든 상태 정보를 포함하는 opengl es 3.0 내부 데이터 구조.
eglcreateContext로 context 생성.
shareContext: 여러 컨텍스트가 특정 유형 데이터 공유 가능.
attribList: egl_context_client_version만 허용됨.
(이거 지정해야하는 이유? 왜 이거해야 올바른 형태를 반환하는거지?
사용중인 es버전과 관련된 유형을 지정해서 버전을 맞추는건가? 14**)
((sharedContext는 지금 알 필요 없음. 하나하나 자세히 용어를 뜯어볼 필요는 없음.))
- Making on eglcontext current
make current란 프로세스가 목적. (특정 eglContext를 렌더링 표면과 연관시키는 방법.
app이 다양한 용도로 여러 eglContext생성했을 수도 있으므로.)
((surface, context 사용해서 드로우하겠다는 게 목적. 이 함수가 없으면 그릴 수 없음.
클래스 set함수 느낌.(property 설정 느낌.)
-> 비싼 함수는 맞음. 일반적 코딩은 surface 1, context 1. 모바일 gpu는 비싼데 다른데서는 비싸지 않을 수도 있음.
그냥 필요하면 쓰는 함수의 느낌.
이 context갖고 surface에 그릴 것. 이 context가 바뀌지 않았다면 굳이 이 함수 호출할 필요 없음.
화면 로테이션할 경우도 해당 함수 호출.
))
eglMakeCurrent((이게 제일 중요.))
display 커넥션 점검
draw: draw surface
read: read surface
context: surfaces에 첨부할 렌더링 컨텍스트 지정.
여기서는 flush필요. (타일 베이스 아키텍쳐는 비효율적.
타일 베이스: 프레임버퍼 전체 매번 갱신이 아닌 타일마다 렌더링하는 것.
드로우콜 발생 시 즉시 프레임버퍼에 기록하는 게 아닌 칩셋에 내장된 메모리 존재하는 타일만 렌더링.
실제 도형 그려지는 타일만 렌더링.)
https://3dmpengines.tistory.com/2045
++드로우콜-cpu frame에 어떤 거 그릴지 정하고 gpu에 오브젝트 그리라고 명령 호출.
- putting all out egl knowledge together
egl초기화~context를 egl surface에 바인딩까지 과정.
(창 생성과 컨텍스트 분리하는 부분 제외하면 나머지는 유사.)
- Synchronizing Rendering -> 어떤 api가 현재 렌더링되어있는지, 모든 렌더링 이뤄졌는지 확인.
그래픽 api 렌더링을 싱글 창에 띄워야 할 수 있음.
다양한 라이브러리를 윈도우에 렌더링하도록 해야 함.
opengl es 3.0으로만 하면 glFinish만 호출하면 됨.
둘 이상의 크로노스api(17**--크로노스: 그래픽스 관련 라이브러리 회사.) 사용+ 윈도우 시스템을 기본 렌더링 api로 전환 전 어떤
api 사용하는지 모를 때
eglWaitClient(): 크로노스api를 통한 모든 렌더링 완료될 때까지 클라이언트 실행 지연.
((openvg에서 그림->위에 opengl 시작해서 그리고 싶을 때 동기화필요할 때 쓰고 싶음.
openvg 안쓸꺼 같아서 넘어가도 됨.))
glFinish와 비슷, 어떤 크로노스api가 작동중인지와 별개로 작동.
(18**glFinish는 크로노스api 다른 거 작동중이면 멈추나?--
glfinish-다른 그래픽스 api 다 렌더링될때까지 결과 나오지 않음.
eglWaitClient-해당 함수 전에 만들어진 렌더링 api는 해당 함수 다음에 만들어진 native rendering call 전에 다 호출되는
거 확인+호출해서 실행되게 설정.
)
((egl이 여러 윈도우 시스템 관리 위해 만들어진 라이브러리.
surface, context 생성 및 eglmakeCurrent함수 써서 만들어야 함.
구현하는데서 어케했는지 차이지 원래 스펙은 안나와야 하는 게 맞음.
opengl이 윈도우에 렌더링 위해서는 egl context 필요. (윈도우 접근 방법은 Egl만 알기 때문.)
어떤 데이터 갖고있는지는 정확하게 모름. egl context: opengl v, egl v 담음. window와 연결해서 opengl그려지도록
설정, 기타 메모리 자원 등 초기화해놓는 것.
--> 상태 정보 담고있다는 개념 정도로 추상화해서 생각하면 됨.
))
((모바일은 화면을 잠궈서 어플에 접근 못하게 만들려고 함.
이 상황에서 context/surface 등 데이터 찾아서 가져오려고 하려고 하면 (background task)
디스플레이켜짐+프레임 상태 바뀌는 상태에서 디스플레이 실제로 키면 최종 버전 팝업 되는건지?
--> 계속 렌더링 가능. 디스플레이도 자신만의 큐가 있음 계속 렌더링 데이터가 쌓이면 못받게 하거나 최신 데이터 받게 하거나
등의 작용 가능. app lifecycle 콜백대로 일반적으로 진행됨.
pose/lockscreen되어도 해당 어플리케이션 렌더링 과정이 붕괴되지 않음.
뒤에서 알아서 백그라운드에 도는 거는 현실적으로 쓰이지 않음.(렌더링은 무거운 작업. 그래서 업데이트/렌더링 둘을 나눔.
렌더링 필요없-업데이트, 렌더링은 최신 상태만 갖고 수행함.
-> 상태관리는 따로 해줘야 함. 결국 업데이트와 렌더링을 분리하기 위해 그렇게 만들어둠.
)
듀얼 모니터 렌더링: egl Context 2개일 때 egl way client 해줘도 됨.
듀얼 모니터 써도 윈도우즈 시스템에서 윈도우를 하나만 보냄. 그래서 surface 하나. 두 개 주면 EglmakeCurrent 사용하면 됨.
eglmakeCurrent에서 draw, read에 pbuffer 넣어도 됨?
--> pbuffer: 윈도우 없을 때 무언가를 만드는 것이므로 가능.
read를 이용해 삼각형을 그릴 때 그려지는 장소가 draw.
현재 모니터에 그려져 있는 것을 read 가능. 이 때 read(내가 읽을 데이터)에 데이터 넣음.
readsurface = drawsurface. 동영상 플레이어 위에 자막 넣고 싶음. 동영상 코덱에서 불러오는거=Read,
draw는 자막을 만들어서 새 버퍼에 넣기.
drawbuffer = default frame buffer.
))
'OSS' 카테고리의 다른 글
OpenGL ES 3.0 스터디 5주차 공부자료 (0) | 2023.08.21 |
---|---|
OSS 8월 회고 후기 (0) | 2023.08.16 |
OpenGL ES 3.0 스터디 4주차 공부자료 (0) | 2023.08.14 |
OpenGL ES 3.0 스터디 2주차 공부자료 (0) | 2023.08.01 |
OpenGL ES 3.0 스터디 1주차 공부자료 (0) | 2023.07.29 |