반응형
Notice
Recent Posts
Recent Comments
Link
«   2024/07   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31
Archives
Today
Total
관리 메뉴

코딩하기 좋은날

Android Graphics 번역 6편 - SurfaceView와 GLSurfaceView 본문

Android

Android Graphics 번역 6편 - SurfaceView와 GLSurfaceView

huiung 2022. 7. 24. 14:44
반응형

출처: https://source.android.com/devices/graphics/arch-sv-glsv

SurfaceView

SurfaceView는 다른 View들과 동일한 종류의 인자를 받으므로, SurfaceView의 위치와 크기를 지정하거나 주위에 다른 UI요소들을 넣을 수 있다. SurfaceView가 rendering 할 때가 되면, 컨텐츠들은 완전히 투명하게 된다.

GL context 또는 media decoder와 같은 외부 buffer 소스로 rendering할 때 buffer를 화면에 표시하려면 buffer 소스에서 buffer를 복사해야 한다. SurfaceView를 사용하면 그렇게 할 수 있다.

SurfaceVIew의 View컴포넌트가 시각화 되려고 할때, 프레임워크는 SurfaceControl 에게 SurfaceFlinger가 새 Surface를 생성하도록 요청한다. Surface가 생성되거나 소멸될 때 callback을 수신하려면 SurfaceHolder 인터페이스를 사용해야 한다. default로 생성된 Surface는 app UI Surface 뒤에 배치되며, Z-ordering을 재정의 해서 위에 배치하도록 할 수 있다.

SurfaceView를 사용한 rendering은 Camera API 또는 OpenGL ES context로 rendering할 때와 같이 별도의 Surface으로 rendering해야 하는 경우에 유용하다.

이 Surface에 무엇을 rendering 하던지간에, App이 아니라 SurfaceFlinger에 의해 합성이 될 것이다.(SurfaceView는 App과는 별도의 Window영역으로 동작한다.) 이것이 Surface의 진정한 장점이다. 얻게 된 Surface는 별도의 thread나 process에 의해 rendering 될 수 있고, app UI에 의해 수행되는 rendering에서 격리 될 수 있으며, buffer들이 직접 SurfaceFlinger에 전달되게 한다. 그러나 UI thread의 동작 전부를 무시할 수는 없다. SurfaceView로 rendering한 후 UI thread를 사용하여 activity lifecycle을 조정하고 필요한 경우 View의 크기 또는 위치를 조정한다. 그런 다음 Hardware Composer는 앱 UI와 다른 레이어를 혼합한다.

SurfaceView and the activity lifecycle

SurfaceView를 사용할 때, Surface는 UI thread가 아닌 다른 thread에서 rendering 된다. SurfaceView가 있는 Activity의 경우 두 개의 개별적이지만 상호 의존적인 state machine이 있다.

  • App onCreate / onResume / onPause
  • Surface created / changed / destroyed

Activity가 시작되면 다음의 순서로 callback을 받게 된다.

  1. onCreate()
  2. onResume()
  3. surfaceCreated()
  4. surfaceChanged()

만약 back()키를 누른다면 다음의 callback을 받을 것이다.

  1. onPause()
  2. surfaceDestroyed()

만약 화면을 회전한다면 isFinishing()을 체크함으로써 빠른 restart를 알려 줄 수 있다. Activity가 아주 빠르게 start/stop 된다면 onPause()이후에 surfaceCreated()가 호출 될 수 있다.

만약 전원 버튼을 눌러 화면을 끈다면 surfaceDestroyed() 없이 onPause()만 받을 것이다. Surface는 이 상황에서 active한 상태로 남아있으며, 끊임없이 rendering을 하고 있을 것이다.

스레드의 수명은 화면이 비어 있을 때 발생하려는 작업에 따라 Surface나 Activity에 연결될 수 있다. thread는 activity start/stop 또는 Surface create/destroy 시 start/stop할 수 있다.

activity start/stop에서 thread를 start/stop하는 것은 앱 lifecycle과 잘 동작한다. onResume()에서 renderer thread를 시작하고 onStop()에서 중지한다. thread를 생성 및 구성할 때 Surface가 이미 존재하는 경우도 있고 존재하지 않는 경우도 있다(예: 전원 버튼으로 화면을 전환한 후에도 여전히 활성 상태임). thread를 초기화하기 전에 Surface가 생성될 때까지 기다려야 한다. Surface가 재생성 되지 않는 경우에는 SurfaceCreated()콜백을 받을 수 없으므로 Surface상태를 쿼리하거나 캐시한다음 rendere thread로 전달해야 한다.

note: thread간 객체를 전달할 때 주의해라. Surface나 SurfaceHolder를 넘겨야 하는 경우 multicore 시스템에서 발생할수 있는 문제를 피하기 위해 Handler message를 이용하는 것이 가장 좋다.

Surface create/destroy에서 thread start/stop를 하는 것은 Surface와 renderer가 논리적으로 얽혀 있기 때문에 잘 작동한다. 화면이 비어 있을 때 rendering을 중지하고 빈 화면이 해제될 때 다시 시작되도록 하려면 Choreographer에게 frame draw callback 호출을 중지하도록 지시하면 된다.

GLSurfaceView

  • OpenGL rendering을 표시하기 위해 dedicated surface를 사용하는 SurfaceView
  • 안드로이드 View 시스템에 합성될 수 있는 특별한 메모리 조각인 Surface를 관리한다.
  • OpenGL이 surface에 rendering 가능하도록 하는 EGL display를 관리한다.
  • 실제로 rendering을 하는 user-provided Renderer object를 받는다.
  • 전용 thread에서 rendering하여 UI 스레드에서 렌더링 성능을 분리한다.
  • on-demand and continuous rendering(default mode) 지원
  • 일반적인 View와 달리, drawing은 GLSurfaceView에 등록된 별도의 Renderer가 처리한다.(setRenderer)
  • default로 GLSurfaceView는 Pixelformat.RGB_888 포맷 surface를 만든다. 만약 투명 surface가 필요하다면 getHolder().setFormat(PixelFormat.TRANSULCENT)를 호출해야 한다.
  • 액티비티 라이프 사이클에 따라, onPause, onResume을 호출해주어야 한다.
반응형