Drawn out: how Android renders (Google I/O ’18)

[음악 재생] 안녕하세요 우리 이야기에 오신 것을 환영합니다

"그려진 것 – Android가 UI를 렌더링하는 방법 " 그것은 거의 다른 것으로 불 렸습니다 우리는 그것을 이것을, 그리고 몇몇 행정부에서 위치가 실제로 가고 있다고 결정했다 "앱을 최적화하는 방법 Top Rendering Performance "또는 뭔가 그 얘기가 아니 었습니다

다행히도, 우리는 그것을 다시 바꿨습니다 ROMAIN GUY : 아직도 그렇지 않습니다 CHET HAASE : 대신에, 우리는 당신에게 어떻게, 사실, 물건이 작동합니다 나는 쳇 하세입니다 나는 안드로이드 툴킷 팀 출신이다

Romain Guy : 나는 Romain Guy입니다 저는 Android 프레임 워크 팀에 있습니다 나는 실시간 그래픽을한다 CHET HAASE : 그것은 오늘날 우리가 이야기하고있는 것과 같습니다 그래서 우리는 이전에이 버전의 버전을 제공했습니다

우리는 우리가 끝난 줄 알았다 그리고 나서 우리는 충분한 것들을 깨달았습니다 어쩌면 시스템 내부에서 바뀌었다 이 일을 다시하고 우리가있는 곳을 볼 시간이었습니다 이것이 우리의 시도입니다

가자 그래서 우선, 렌더링이라는 단어가 있습니다 그게 무슨 뜻이야? 일반적으로 그것을 명확히하기 위해 지방을 녹이는 것을 의미합니다 그것은 우리가 오늘 이야기 할 내용이 아닙니다 대신, 우리는 실제로 선회하는 과정에 대해 이야기하고 있습니다

버튼과 체크 상자와 같은 모든 것들 화면의 모든 것을 픽셀 단위로 사용자가 볼 수있는 그리고 많은 일들이 진행되고 있습니다 우리가하는 많은 세부 사항이 있습니다 우리는 오직 오늘부터 이것을 40 분 안에하십시오 그러나 우리는 그 길을 따라 많은 세부 정보를 덤프 할 것입니다 그래서 우선, 나는 너를 데려 갈거야

~을 통해 색깔의 무리가 될 것입니다 상단에 도트가 표시됩니다 이야기의 나머지 부분에 대한 시각적 단서의 종류 그래서 저는 일종의 걸음마 단계를 밟을 것입니다 정보의 흐름에서 일어나는 일생의 화면의 픽셀까지 내려갈 수 있습니다 우리는 안무가라고 불리는이 물건을 가지고 있습니다

보통 60 초에 한 번 찰 때, Vsync라고합니다이 간격은 다음과 같습니다 프레임이 동기화되고 있습니다 버퍼가 화면에 나타납니다 우리가 많은 정보를 처리 할 좋은 시간입니다

그 정보의 렌더링 처리 그 결과로 Vsync 연산을 얻습니다 Java SDK 영역으로 보내졌으며 우리는 UI 스레드를 사용하고 있습니다 그리고 갑자기 우리는 입력 이벤트를 처리해야합니다 속성의 변경 사항을 트리거합니다 우리는 또한 모든 애니메이션을 실행합니다

그래서 우리는 속성 값을 변경합니다 다시 말하지만, 레이아웃 및 무효화와 같은 일이 발생할 수 있습니다 우리는 전체 통과 통과를 측정합니다 그들이 얼마나 큰지 알아 내기 위해서, 그것들을 실제로 배치하는 것입니다 어디로 가야하는지, 그리고 그 다음에 그려야합니다

일단 모든 정보가 완료되면, 해당 정보의 결과를 동기화합니다 렌더링 스레드라고 불리는 것에 이르기까지 그리고 렌더링 스레드가 그것을 받아서, 좋아, 글쎄, 나는 이것들을 실행하려고합니다 나는 기본적으로 이것을 돌릴거야 모든 정보의 기본 버전으로 우리는 Java 레이어에서 제작 한 다음 GPU에서 버퍼를 얻으려고 할 때, 그래서 나는이 정보를 쓸 곳이있다

그리고 나서이 모든 GPU 명령을 실제로 발행 할 것입니다 저기있는 OpenGL 같은 것들 그리고 나서 저는 말할 것입니다 좋아요, 이제는 버퍼를 바꿀 때가되었습니다 그런 다음 GPU로 넘깁니다

그리고 그래픽 시스템은 합성이라고하는 것, 우리는 오늘이 단계의 대부분에 대해 이야기 할 것입니다 그래서 합성은 생각합니다 우리는 전에 결코 설명하지 못했습니다 그래서 우리는 약간의 세부 사항을 들어갈 것입니다 안드로이드 렌더링 아키텍처의이 부분에 대해서

그럼 작은 색 점들 화면 상단에 주목할 것입니다 우리는 몇 가지 예를 거쳐 과정을 진행하고 있으며, 우리는 이것을 더 잘 이해할 수 있습니다 예제를 말하면, 여기 간단한 예제가 있습니다 따라서 사용자가 있다고 가정 해 봅시다 사용자가 항목을 클릭하면 나는이 굉장한 RecyclerView 응용 프로그램을 썼다

그 모양이 정확히 같습니다 나는 그것이 스크린 샷이기 때문에 그것이라는 것을 안다 내 멋진 응용 프로그램에서 그것에는 아이템이 잔뜩 들어있는 RecyclerView입니다 사용자가 하나를 클릭하면이 놀라운 일이 발생합니다

그것은 배경에 임의의 색상으로 변합니다 그것은 믿을 수 없다 나는 너에게 근원을 줄 수 있었지만 나는 모른다 그것은 꽤 복잡합니다 네가 이해할 수 있을지 확신 할 수 없다

여기 내 놀라운 데모 응용 프로그램을위한 놀라운 레이아웃이 있습니다 ConstraintLayout이 있습니다 내부에 RecyclerView가 있습니다 그런 다음 런타임에 채 웁니다 그 안에는 무작위적인 물건들이 잔뜩 있어요

이 것에 대한 뷰 계층 구조 기본적으로 이렇게 보입니다 실제로, 그것은 기본적으로 이와 같이 보이지 않습니다 그것은 정확히 이것과 같습니다 그래서 당신은 DecorView에서 내려갑니다 LinearLayout과 FrameLayout이 있습니다

나는 왜 우리가 깊은 둥지를 틀고 있는지 정확히 알지 못한다 하지만 뭐든간에 역사 우리는 거기에 행동 바에 대한 것들을 잔뜩 가지고 그게 정말 중요하지 않습니다

우리가 여기서 염려하는 것은 콘텐츠 계층 구조에서 실제로 무슨 일이 일어나고 있는지, 그것이 응용 프로그램에 영향을 줄 수 있기 때문입니다 그래서 우리는 내용 FrameLayout, 우리는 ConstraintLayout을 가지고있다 바깥쪽에는 RecyclerView를 감 쌉니다 그리고 나서 모든 항목 구체적으로 이들은 다음과 같은 항목입니다

그것들은 유일한 것들이기 때문에 화면에 있습니다 실제로 측정되고 배치되고 그려집니다 그래서 어떻게됩니까? 이 예제를 실행하고 우리가 처음부터 끝까지 간 모든 흐름을 통해 사용자가 클릭하면 Vsync 작업이 실행됩니다 그것이 전송되고 입력 단계에서 입력을 처리합니다 우리는 이것이 클릭이라는 것을 알게됩니다

나는 여기에 몇 가지 세부 사항에 광택을 쓰고있다 사실, 우리는 먼저 다운이 있다는 것을 알아 차릴 것입니다 그런 다음 위로 올라간 다음에 클릭으로 처리됩니다 우리가 결국은 당연한 것으로 받아 들여 여기를 클릭하여 처리 할 것입니다

이 항목에서 클릭 끝나는 방법 내가 가지고있는 놀랍도록 복잡한 예에서, 그 안에 배경색을 설정합니다 이 항목에 임의의 색상을 지정하십시오 그것이 내가이 방법을 무작위로 호출 한 이유입니다 viewjava에서 설정된 배경색으로 전송됩니다

배경에 색상을 설정하는 물건을 잔뜩합니다 drawable, 그리고 나서 결국 호출 이 메소드는 invalidate라고 불린다 무효화는 프로세스입니다 실제로 뷰를 다시 그리지는 않습니다 View Hierarchy에 무엇인가를 알려주는 과정입니다

다시 그려야합니다 그래서 클릭이 발생합니다 그것은 아래쪽에있는 항목에서 발생합니다 그 두 번째 아이템 – 당신은 녹색으로 둘러싸인 것을 보았습니다 우리는 약간의 무효화 메소드가 있습니다

그걸 부름 받았고 기본적으로 나무 위로 걸어 간다 나무 위로 줄곧 일련의 메소드를 호출합니다 뷰는 다시 그려야한다는 것을 알고 있기 때문에, 하지만 실제로 그 정보를 전파해야합니다 계급을 따라 올라간다 그래서 그때 우리는 앞으로 모든 것을 다시 그릴 수 있습니다

그래서 무효 심판을 계층 구조의 맨 위로 불러옵니다 결국 그것은 거대한 수업으로 끝납니다 우리가 ViewRootImpljava를 호출했다고하자 거기에이 무효화 자식 메소드가 있습니다

그리고 그것은 기본적으로 좋아, 나는 순회 일정을 잡아야한다 알았어, 누군가 정보를 가져 왔어 어딘가에서 무효화 됐어 즉 나중에 트래버스 코드를 실행해야합니다 이 과정이 끝나면 순회는 일을하는 과정입니다

실제로 필요한 모든 단계 해당 프레임을 렌더링합니다 구체적으로 말하자면, 보기가 얼마나 큰지, 레이아웃 – 뷰의 위치와 크기를 설정하고 뷰를 그립니다 이 모든 것을 순회라고합니다 그래서 우리는 순회를 계획했습니다 그것은 나중에 일어날 것입니다

그리고 나중에 시간이 지금이다 그래서 같은 프레임에서 우리는 traversal 코드로 끝납니다 이 performTraversals 메소드에서 그것은 PerformDraw를 할 것입니다 PerformDraw는 무승부를 요구합니다

메소드를 핵심 뷰에 추가하면됩니다 모든 방법으로 전파됩니다 그리기 방법은 실제로 최적화에서 끝납니다 허니 콤에서 다시 구현 한 Get DisplayList를 호출합니다 따라서 DisplayList는 렌더링을 저장하는 구조입니다 정보? 버튼 코드의 작성 방법을 보면 또는 일반적으로 코드보기, 그래픽 명령 호출 DrawBackgrounds, DrawDrawable, DrawLine, 도대체 무엇이

그러나 이것들은 DisplayList의 연산으로 끝납니다 이는 이러한 작업을 나타내는 간결한 방법이며, 뿐만 아니라 작업에 대한 매개 변수도 제공합니다 그래서 Get DisplayList를 호출합니다 사실 장식보기는 변경되지 않았습니다 그래서, 글쎄요, 저는 변하지 않았습니다

하지만 확실히 내 아이를위한 DisplayList를 얻을 수 있습니다 그리고 나무 아래로 내려 가면서, 그것이 항목 2에 도착할 때까지, 그리고 그것은 말합니다, 오, 나는 변했습니다 무효가 나를 불렀을 때, 뭔가를 유발해서 내가 다시 새겨 져야한다는 것을 알았습니다 그래서 Get DisplayList 실제로 끝납니다 뷰를 그리는 호출로서 재생성됩니다

자체 디스플레이 목록 자 이제이 onDraw 메서드로 끝납니다 DisplayList에있는 작업으로 끝납니다 DisplayList는이 항목에 대해 기본적으로 rect 정보와 텍스트 정보 – 꽤 기초적인 그리고 기본적으로 DisplayList가 있습니다

전체 계층 구조 그래서 그 자체가보기 자체가 아니 었습니다 하지만 우리는 계층 구조 자체를 가지고 있습니다 이 표시 목록의 계층 구조에서 재생됩니다 줄곧

이제 전체 트리에 대한 DisplayList가 있습니다 그게 우리가 UI 스레드에서해야 할 모든 것입니다 이제 우리는 그 정보를 렌더링 스레드 및 렌더링 스레드 GPU를 실제로 다루는 별도의 스레드입니다 이 작업의 측면 Java 측에서는 모든 정보를 생성했습니다

네이티브 측에서, 우리는 실제로 – 우리는 그 정보를 가지고 GPU로 동기화합니다 동기화 작업이 있습니다 기본적으로 우리는 저기서 핸들을 복사 해 또한 관련 정보를 일부 복사합니다 피해 지역을 복사 했으니 까

그 아이템 2 – 그게 중요하다는 걸 아는 것이 중요합니다 그 틀에서 변한 유일한 것 우리가 아무것도 다시 그릴 필요가 없다는 것을 의미한다 그렇지 않으면 그 지역 밖 그래서 우리는 클립 바운드를 복사 할 것입니다

그래서 우리는 다시 그려야 할 것을 알고 있습니다 이제 최적화를 수행 할 것입니다 비트 맵 업로드 같은 것들 따라서 이것은 프레임의 시작 부분에서 그것을 수행하기에 좋은 시간입니다 그들에게 실제로 그들을 돌려 줄 시간을주세요

길을 따라 텍스처에, 우리는 다른 것들을하고있어 ROMAIN GUY : 여기에 우리가 업로드 중임을 언급합니다 하드웨어가 아닌 비트 맵 하드웨어 비트 맵은 새로운 유형의 비트 맵 구성입니다 Android O에 추가되었습니다 일반적으로, 비트 맵을 가지고있을 때 메모리를 할당해야합니다

자바 측에서 그리고 그릴 시간이 왔을 때, 우리는 GPU에서 비트 맵 복사본을 만들어야합니다 이것은 비싸다 시간이 걸리며 사용하는 RAM의 양이 두 배로 늘어납니다 따라서 Oreo에서 사용 가능한 하드웨어 비트 맵을 사용하면, 당신은 방정식의 Java 측을 유지할 수 있습니다

GPU에만있는 비트 맵을 가질 수 있습니다 따라서이 비트 맵을 다시 수정하지 않을 경우, 이것은 메모리 효율적인 현명한 효율적인 방법입니다 비트 맵의 ​​메모리를 저장합니다 CHET HAASE : 이전에 렌더링 스레드에 대해 언급했습니다 이것은 우리가 롤리팝에서 소개 한 것입니다

해제 GPU 와만 통신하는 별도의 스레드입니다 그것은 네이티브 코드입니다 Java 코드 외부에는 호출이 없습니다 애플리케이션 코드에는 분명히 콜 아웃이 없다

그냥 GPU와 대화합니다 우리는 이것을했습니다 그래서 우리는 여전히 기본적으로해야합니다 우리가했던 것과 같은 일, 미리 렌더링 된 쓰레드, 우리는 모든 DisplayList 정보를 생성합니까? 그 다음 DisplayList 정보를 보냅니다 GPU에

그래서 일련의 직렬하지만 렌더 스레드 원형처럼 물건을 원자 적으로 할 수있다 리플 애니메이션뿐만 아니라 애니메이션도 보여줍니다 벡터 드로어 블 애니메이션으로서 – 렌더링 스레드에서 원자 적으로 발생할 수 있습니다 그래서 일어날 수있는 일 UI 스레드를 정지시키지 않아도됩니다 그리고 그 동안 UI 스레드 유휴 상태 일 때 다른 일을 할 수 있습니다

동기화 후, 유휴 프리 페치 중 일부 작년에 한 RecyclerView에서 일합니다 따라서 스레드가 실행됩니다 우리는 모든 것을 동기화했습니다 우리는 DisplayList를 가지고 있습니다, 피해 지역이 있습니다, DisplayList를 무언가로 바꿉니다 우리가 DLOps라고 부르는 것 – 표시 목록 조작

따라서 중간에 채우기 작업이 있음을 알 수 있습니다 그것이 우리가 녹색으로 변한 것입니다 그런 다음 우리는 우리가 수행하는 최적화가 있습니다 ROMAIN GUY : 여기서 우리는 다양한 최적화 작업을 수행합니다 그래서 예를 들어, 알파 렌더링을한다면 뷰에 Set Alpha를 호출하거나 하드웨어를 설정 한 경우 레이어를 선택하면 그리기 명령을 식별하려고합니다

해당 레이어를 대상으로해야하는 프레임의 시작 부분에서 이동시킵니다 이렇게하면 GPU 내부의 상태 변화를 피할 수 있습니다 매우 비쌉니다 따라서 이런 종류의 최적화를 수행하지 않고, 당신은 끔찍하고 끔찍한 성적을 보게 될 것입니다 GPU 자체가 느려지 기 때문이 아닙니다

GPU가 CPU를 기다리고있을뿐입니다 그것을 지시하기 위해 우리가하고있는 다른 하나, 우리는 당신에게 실제적인 실제적인 예를 보여주기 위해, 재정렬 및 ​​매칭이라고합니다 우리는 모든 작업을 살펴보고, 우리가 목록 항목을 가지고 있기 때문에이 예제에서 볼 수 있습니다 우리는 유사한 많은 작업을 인터리빙합니다

그래서 우리는 직사각형을 그릴 것입니다 그리고 나서 텍스트를 그릴거야 그런 다음 사각형과 텍스트를 다시 그릴 것입니다 그리고 다시 여기에서 우리는 GPU의 상태를 바꾸고 있습니다 여러 번, 대신에 우리는 명령어가 겹치지 않으면 할 수있다

우리는 모든 직사각형을 함께 그릴 수 있습니다 그리고 나서 우리는 모든 텍스트를 함께 그릴 수 있습니다 이것은 재정렬과 매칭의 일부입니다 그리고 때때로, 우리가하는 일은 우리가 말하길, 우리가 사용하는 많은 텍스트를 볼 수 있다면 동일한 색깔 및 동일한 글꼴, 다른 텍스트 불러 오기가 필요하지 않습니다 그것들은 전체 화면을 커버하는 단 하나의 것일 수 있습니다 CHET HAASE : 원본 DLOps를 볼 수 있습니다 채우기 작업을 한 다음 어떤 텍스트를 그리기를 원한다

텍스처 맵이 될 것입니다 글리프 캐시에서 복사합니다 그런 다음 채우기 작업이 있고 그 다음에 더 많은 텍스트와 채우기 그래서 우리는 이러한 모든 작업을 인터리브했습니다 따라서 재정렬 작업 후에, 그러면 좀 더 보입니다

일련의 채우기와 일련의 텍스트 작업이 있습니다 함께 배치 할 수도 있습니다 더 최적이 될 것입니다, 우리는 여기서 볼 것입니다 ROMAIN GUY : Gmail의 예입니다 그래서 그것은 허니 콤 시대에있었습니다

여기서 어떻게 파이프 라인을 수정했는지 알 수 있습니다 렌더링 속도를 늦추고 볼 수 있습니다 Gmail이 그리는 방법을 정확하게 설명합니다 그래서 우리는 많은 목록 항목을 가지고 있습니다 그것들을 정확한 순서대로 그려라

뷰 계층 구조에 코드 순서대로 존재해야합니다 사실은 캔버스에 그린 모든 그리기 호출은 그 명령을 존중해라 불행히도, 내가 말했듯이, 그것은 매우 비효율적입니다 대신에 일괄 처리 및 병합 및 재정렬 한 후, 우리는 이것을 얻는다

특히 모든 별들이 같은 시간에 그려지며, 대부분의 텍스트가 한꺼번에 나타납니다 흥미로운 점은 모든 목록을 그리는 것입니다 항목 배경이 차례로 나타납니다 그래서 좋았어 재정렬이 효과가있었습니다

일괄 처리가 작동하지 않았고 부분적으로 목록이 항목이 약간 겹쳐 있습니다 명령이 겹칠 때 우리는 명령을 하나로 그려야합니다 블렌딩을 존중할 다른 후, 알파 값이 올바른지 확인하십시오 따라서 효과는 실제로 응용 프로그램에 따라 다릅니다 KitKat에서 올바르게 기억한다면, 설정 응용 프로그램은 전체 화면을 그릴 수있었습니다

수십, 수십 개가 아닌 약 6 회의 무승부 요청으로, 뷰 계층 구조에서 볼 수 있습니다 따라서 이것은 우리에게 매우 중요한 최적화입니다 CHET HAASE : 나는 현재의 장치들에 대한이 작업을 생각한다 밀리 초와 같은 것을 저장했다 우리가 가진 것을 깨닫지 못한다면 16 세 안에 모든 것을 할 수 있습니다

그래서 실제로 큰 발전이었습니다 Gmail 덕분에 Gmail이 덜 복잡해질 수있었습니다 종종 다음 프레임으로 밀려 나왔다 그래서 모든 것에 대한 우리의 설명으로 되돌아갑니다 그런 다음 clipReject가 있습니다

그래서 이것은 우리가 피해에 대한 정보를 얻는 곳입니다 지역? 그래서 우리는 두 번째 항목이 화면에 있었는지 알고 있습니다 우리는 우리가 그릴 필요가 없다는 것을 안다 그 밖에는 아무것도 없어 따라서 우리는이 DLOps를 처리하면서, 우리는 기본적으로 버릴 수 있다는 것을 압니다

그 지역 밖에서 그려지고있는 모든 것 그래픽에서는 사소한 불량이라고합니다 따라서 우리는 모든 DLOps를 사소하게 거부합니다 그 지역과 교차하지 않은 이제 우리가해야 할 일은 채우기를 그리는 것뿐입니다 그리고 일부 텍스트와 라인

그래서 우리는 그렇게합니다 이를 수행하는 과정에서 우리는 GetBuffer를 수행 할 수 있습니다 이것은 대개 암시 적 작업입니다 우리는 완충을 요구하지 않는다 GPU 작업을 시작하자 마자, 그러면 GPU가 우리에게 버퍼를 넘깁니다

특히, SurfaceFlinger가 우리에게 버퍼를 건네줍니다 우리는이 명령들을 넣을 수 있습니다 그런 다음 명령을 실행합니다 이것은 일련의 GL 명령입니다 슬라이드에서 볼 수 있듯이 glCommand라고합니다

기본적으로 우리가 무엇을 필요로하는지에 상응합니다 채우기 또는 텍스트 수행하기 – 비트 맵은 줄을 복사합니다 그리고 우리는 버퍼를 교환합니다 그래서 이것은 우리가 말하고있는 것입니다, 우리는 우리의 모든 렌더링 작업 이 프레임을 화면에 표시 할 준비가되었습니다

SurfaceFlinger가 버퍼를 교환하라는 요청입니다 기본적으로, 우리는 버퍼로 드로잉을 마쳤습니다 앞면에있는 것과 이것을 바꿀 수 있습니다 그것을 화면에 표시합니다 한편, SurfaceFlinger에서 우리는 Romain이 가고있는 합성 단계가있다

나중에 많이 이야기하기 하지만 기본적으로 화면의 모든 창을 차지합니다 탐색 막대, 상태 표시 줄, 응용 프로그램의 실제 내용 창 그것은 하드웨어 컴포 지터에있는 모든 것을 결합합니다 그들을 화면에 놓은 다음, 타다 끝났어

그래서 정말 간단한 예였습니다 매우 복잡한 예를 살펴 보겠습니다 이것은 두 단계로 진행될 것입니다 하나, 그래서 우리는 목록을 끌어 올거야 그래서 우리는 그것을 끌고 갈 것입니다, 그리고 우리가 그것을 끌고 갈 때, 우리는 항목을 조금씩 옮길 것입니다

그리고 결국 우리가 계속 움직이면, 우리는 새로운 아이템을 나타낼 것입니다 그래서 우리는이 두 가지 버전을 살펴볼 것입니다 이동 전용 버전이 있습니다 그래서 우리가 그것을 끌어 올릴 때, 새로운 아이템 – 새 항목이 표시되지 않습니다 모든 것이 조금 바뀌 었습니다

우선 우선 처리해야합니다 그래서 우리는 Vsync를 가지고 있습니다 입력 이벤트를 처리 할 시간입니다 그래서 우리는 그렇게하고, 우리는 이런 식으로 끝납니다 RecyclerView의 터치 이벤트에서 잘, 아래 가동이 있었다는 것을 밝힌다

그리고 등록 만하면됩니다 그 일이 일어난 곳 아무것도 처리 할 필요가 없습니다 화면에서 아무 것도 바뀌지 않았습니다 우리는 방금 사용자가 실제로 눌렀다는 것을 등록했습니다

그래서 우리는 그것을 나중에 기록하고 아무런 작전도 없습니다 우리는 우리가 얘기 한 나머지 것들은하지 않습니다 아무것도 바뀌지 않았기 때문에 그들은 드래그를 계속하고 유사한 코드로 끝납니다 그래서 우리는 다음 프레임에서 입력을 처리합니다

우리는 터치 이벤트에서 OK라고 말합니다 오, 이제 우리는 그들이 실제로 움직 였다는 것을 알고 있습니다 우리는 이전 X를 저장했기 때문에 그들이 얼마나 많이 움직 였는지 압니다 우리는 델타를 계산합니다 그리고 이제 우리는 offset top와 bottom이라고 불리는 것을 호출합니다

기본적으로 화면의 모든보기에 대해 우리는 단순히 Y로 그들을 이동합니다 그리고 위쪽과 아래쪽 호출 오프셋 무언가 무효화 방법입니다, 하지만 약간 다릅니다

그것은, invalidateViewProperty 말한다 이것은 우리가 두는 최적화입니다 아마 허니 콤 두 번째 릴리스 또는 무언가 DisplayList 속성 그래서 이전에 DisplayList에 대해 이야기했을 때, 내가 빠뜨린 하나의 뉘앙스가있었습니다 우리는 운영에 관한 정보를 가지고 있습니다 그리고 그래픽 작업을위한 매개 변수

하지만 일부 핵심 디스플레이에 대한 정보도 있습니다 기본적으로 뷰의 속성 인 속성, 번역 속성과 마찬가지로 회전 알파 그리고 이것들은 우리가 필요로하지 않는 속성입니다 변경하려는보기를 다시 렌더링합니다 우리는 단순히 DisplayList 구조 자체에서 그것들을 변경할 수 있습니다

그런 다음 GPU 발행시에 선택됩니다 따라서 우리가 그렇게하는 것이 매우 빠릅니다 따라서보기를 무효화하는 대신 그 모든 것을 모두 다시 그리는 것 우리가하는 말은 번역을 바꾸는 것입니다 이보기의 속성 그래서 우리는 invalidateViewProperty를 호출합니다 그것은 나무 위로 모든 길을 전파합니다

우리는 여전히 최상위 계층에서 어떤 일이 발생 하는지를 알아야하기 때문에, 하지만 훨씬 더 최적의 단계입니다 이렇게되면 일정이 정해진 다 Traversals, 이전처럼 추첨에서, 그것은 performTraversals에서 끝나고, PerformDraw는 이보다 훨씬 간단한 버전을 수행 할 수 있습니다 DisplayList가 실제로 변경되지 않았기 때문입니다

DisplayList 속성을 변경하면됩니다 그것의 내부 그래서 우리는 즉시 그 정보를 렌더링 스레드로 그런 다음이를 실행하여 DisplayList 연산으로 변환 할 수 있습니다 버퍼를 얻는다

기본적으로 모든 것은 이전과 같습니다 두 번째 단계로 가자 그 복잡한 복잡한 예입니다 사용자는 드래그를 계속하고, 드래그 할 때, 하단에 새 항목이 나타납니다 따라서 Vsync는 입력을 처리합니다

우리는 이와 같은 방법으로 끝납니다 우리는 그들이 움직 였다는 것을 압니다 오,하지만 그건 우리가 창조를 촉발시킬 필요가 있음을 의미합니다 그리고 거기에 새 항목의 바인딩 결국이 코드에서 끝납니다

상위 뷰를 추가하십시오 그래서 RecyclerView는 새로운 시각을 갖게 될 것입니다 RequestLayout을 호출 할 것입니다 그래서 RequestLayout은 일종의 무효화입니다 그러나 말하는 대신에, 나는 다시 그려야한다

그것은, 내가 다시 측정하고 relaid 필요가 말합니다 그리고 그것은 모든 사람들에게 영향을 미칠 수 있습니다 그래서 우리는 기본적으로 RequestLayout을 모든 방법으로 전달합니다 무효처럼 나무를 올리십시오 그런 다음 전체 트리에서 측정 및 레이아웃을 수행합니다

거기서 무엇이 바뀌 었는지 보러 그래서 RequestLayout은 부모에서 일어나고, 그리고 그 모든 것이 전파됩니다 그리고 그것은 다시 일정에 잡 힙니다 여행자, 우리 친구 그런 다음 트래버스를 수행하십시오

지금 그릴 물건에 대해 우리는 performMeasure를 할 것입니다 및 performLayout 측정은 기본적으로 모든 의견을 묻습니다 그들이 얼마나 큰 지 알고 싶습니다

그것은 요청입니다 레이아웃이 말하길, 이것은 당신이 얼마나 커질 지에 대한 것입니다 그리고 이것은 당신이 위치 할 곳입니다 그것은 견해와 모든 부모 사이의 협상이다 시스템의 모든 제약 조건에 따라 그래서 우리는 수행을 수행합니다

그것은 기본적으로 측정을 상단에서 호출합니다 그 모든 것이 아래로 전파됩니다 그리고 우리는 모든 정보를 가지고 있습니다 모든 견해가 얼마나 커지고 싶어하는지, 그게 우리가 레이아웃을 계산하기에 충분하다 정보

그런 다음 레이아웃을 트리 전체로 전파합니다 그리고 그 일이 아이템과 부모에게 일어나면 변경된 다음, 실제로 그 항목을 배치합니다 우리는 갈 준비가되어 있습니다 이제 우리는 실제로 물건을 그릴 수 있습니다 모든 것은 이전과 같습니다

여기서 뉘앙스는 단지 레이아웃면이었습니다 중요한 뉘앙스를 제외하고는 우리 모두가 이 RequestLayout과 측정 및 레이아웃에 대한 정보 이 RecyclerView 상황 그러나 RecyclerView는이를 최적화합니다 부모와 자녀에 대해 충분히 알고 있습니다 실제로는 뷰를 상쇄 할 수 있습니다

RequestLayout을하는 대신, 실제로는보기를 이동시킬 수 있습니다 새 항목을 만듭니다 따라서 RecyclerView, 이전 목록보기뿐 아니라 ROMAIN GUY : 이제 우리는 이야기 할 것입니다 우리의 윈도우 컴포지션 인 SurfaceFlinger가, 화면의 모든 창을 합성합니다 이것은 흥미 롭습니다

음, 우선, 뭔가를 배우는 것이 항상 재미 있기 때문입니다 새로운 기술에 대해서뿐만 아니라 이해할 수 있기 때문에 어떤 개념 뒤에 일부 개념 Surface API, SurfaceTexture API, SurfaceView 또는 MediaCodec 그래서 우리가 구성을 이해하기 전에, 우리는 안드로이드에 대한 매우 중요한 개념을 이해해야합니다 버퍼 큐를 호출했다 따라서 이름에서 알 수 있듯이 버퍼 대기열은 우리의 그래픽 버퍼가있는 버퍼 큐에 불과합니다

일반적으로 1 ~ 3 개의 버퍼가 있습니다 내부적으로 다양한 옵션이 있습니다 여기서 우리가 버퍼 큐를 설정할 때, 우리가 원하는 버퍼 수를 요청할 수 있습니다 그리고 매우 중요하게도 버퍼 큐는 두 개의 끝점을 가지고 있습니다 우리에게는 생산자가 있고 우리에게는 소비자가 있습니다

따라서 일반적으로 버퍼 대기열을 사용하는 방법 – 생성자는 dequeueBuffer라는 메서드를 호출합니다 대기열에 있습니다 대기열에서 버퍼를 가져옵니다 이제는 그것을 소유하고 있습니다 그것은 모든 종류의 렌더링을 할 수 있습니다

이것은 픽셀 데이터를 직접 전송할 수 있으며, 그것은 OpenGL을 사용할 수 있습니다, 그것은 캔버스를 사용할 수 있습니다 별로 중요하지 않습니다 OpenGL을 사용하면 기본적으로 마지막에 썰매 버퍼를 호출하면 어떻게됩니까? 그 때 우리는 버퍼 안에 내용을 생성합니다 따라서 제작자가 컨텐트를 제작할 때, 그것은 큐 버퍼를 호출하고, 버퍼에 다시 준다 버퍼 큐에 저장한다

이제 소비자는 다음 버퍼를 잡을 수 있습니다 acquire를 사용하여 대기열에 있습니다 그래서 그것은 획득 버퍼를 호출합니다 큐 내의 최초로 이용 가능한 버퍼 그것은 그것과 관련이있는 것은 무엇이든합니다

그리고 그것이 끝나면, 그것은 release를 호출함으로써 그것을 되돌립니다 그래서 아주 간단한 개념입니다 물론 코드를 보면 모든 헤더 파일과 모든 코드 복잡하다 부분적으로 복잡하다 버퍼 큐의 두 끝점 다른 프로세스에서 살 수 있습니다

그리고 이것은 정확하게 일어납니다 이것은 우리의 곡면 작곡가가 작동하는 방식입니다 따라서 시스템에 창을 만들 때, Window Manager가 있고 SurfaceFlinger가 있습니다 따라서 창 관리자는 효율적입니다 이 시나리오의 제작자 및 SurfaceFlinger 우리의 소비자입니다

그래서 addView에서 Window Manager를 호출하면 – 이 작업은 자동으로 수행됩니다 당신은 토스트를 만들 때 대화를 만들고, 나는 믿습니다 활동을 만들 때 – 내부적으로 우리는 윈도우 객체를 생성한다 이 윈도우 객체는 SurfaceFlinger면에 형제가 있습니다 레이어라고합니다

이름은 조금 혼란 스러울 수 있습니다 그래픽에서는 버퍼와 대기열을 처리해야하기 때문에, 그것이 우리 모두가하는 일이며 우리는 빨리 이름이 없어집니다 그리고 그래픽 팀 – 그게 우리가 생각한 이유야 표면 및 표면 텍스처와 버퍼 큐 및 레이어 및 창 네

그래서 좀 지저분 해 그래서 SurfaceFlinger에 하나의 레이어가 있습니다 그것은 기본적으로 창입니다 레이어가 시스템의 구성 요소입니다 이는 응용 프로그램에 대한 버퍼 대기열을 생성하고 소유합니다

그래서 그것은 버퍼 큐를 생성하고 우리는 애플리케이션에 엔드 포인트를 보내는 방법이있다 서페이스를 만듭니다 따라서 API 중 하나에서 Surface를 볼 때마다 당신은 정말로 버퍼 큐의 프로듀서 끝 점이 있습니다 귀하의 프로세스에서 시스템의 다른 어딘가에 살고있는 또는 일부 다른 프로세스에서 대부분의 시간은 SurfaceFlinger 내부에있게 될 것입니다

이제는 전형적인 유스 케이스로, 애플리케이션 개발자로서 Surface API를 다루려고한다 SurfaceView를 만들 때 따라서 SurfaceView가 작동하는 방식은 자체 표면 인 창입니다 우리가 여기에서 볼 수 있습니다 그럼 우리는 그 표면을 통해 구멍을 효과적으로 잘라 냈습니다

그리고 창 관리자와 SurfaceFlinger에게 물어 봅니다 두 번째 서페이스를 만듭니다 그리고 우리는 그것을 밑으로 밀어 넣습니다 그것들이 같은 창문의 일부인 척하십시오 그러나 그들은 그렇지 않습니다

그것들은 두 개의 다른 표면입니다 그들은 두 개의 서로 다른 버퍼 큐를 가지고 있는데, 그들은 서로 완전히 독립적 일 수 있습니다 따라서 SurfaceView를 사용하면 아마도 OpenGL이나 Vulcan이나 미디어 플레이어를 사용할 것입니다 콘텐츠를 생성합니다 예를 들어,이 경우 OpenGL ES가 있습니다

짐을 뽑아 버릴거야 그것은 약간의 렌더링을 할 것입니다 버퍼를 Surface로 대기열에 넣고, 따라서 버퍼 큐에 저장됩니다 표면 질감을 사용하면 소비자가 OpenGL이됩니다 그래서 텍스쳐 ID를줌으로써 SurfaceTexture를 만듭니다

이 경우 SurfaceTexture가 생성하고 소유합니다 버퍼 큐, 그래서 종종 자신의 프로세스에있을 것입니다 그런 다음 SurfaceTexture를 전달해야합니다 어떤 제작자에게, 그리고 이것을하기 위해, 자신이 엔드 포인트를 작성하고, 서페이스를 만듭니다 SurfaceTexture를 취하는 Surface의 생성자가 있습니다

그래서 당신은 당신의 서피스를 만들고 그것을 보냅니다 다른 응용 프로그램으로 이동 한 다음 OpenGL 코드를 렌더링 할 준비가되면, 그것은 acquire를 호출하여 버퍼 큐에서 버퍼를 가져옵니다 렌더링을 수행합니다 다른 큐의 내부에 버퍼를 생성합니다 완료되면 릴리스를 호출 할 수 있습니다

TextureView는 UI 툴킷의 일부인 위젯입니다 SurfaceTexture의 혜택을 누릴 수 있습니다 이 특별한 경우 렌더링 스레드 우리가 얘기 한 것은 SurfaceTexture의 소비자입니다 당신은 여전히 ​​Surface를 얻는 책임이 있습니다 TextureView에서 그것을주고 당신이 선택한 프로듀서에게

당신은 그것을 멋진 이미지라고 생각할 수 있습니다 정말 효율적으로 업데이트 할 수있는 이미지보기입니다 하드웨어 가속을 사용합니다 최근 몇 년 동안 우리는 당신에게 말 했었습니다 TextureView가 해결책이었습니다

SurfaceView의, 비디오 또는 OpenGL을 통합하고자 할 때 복잡한 응용 프로그램 내에서 렌더링 예를 들어, ListView 또는 CountView 또는 움직이는 모든 것 SurfaceView는 두 개의 다른 창으로 구성되어 있기 때문에, 자연적으로 그렇게 효율적이었습니다 렌더링과 동기화되지 않았습니다 자신의 응용 프로그램의

이 문제는 Android 최신 버전에서 수정되었습니다 그래서 대부분의 시간, 안드로이드의 최신 버전에서, TextureView 대신 SurfaceView를 사용해야합니다 필요한 경우에만 TextureView를 사용하십시오 어쩌면 당신의 다른 견해들 사이에 끼어 있을지도 모릅니다 또는 SurfaceView에서 지원하지 않는 애니메이션을 사용하십시오

CHET HAASE : O 릴리스라고 생각합니다 그건 O– 어쩌면 N 이네 어쩌면 ROMAIN GUY : 둘 중 하나 테스트를해야합니다

CHET HAASE : 우리가 최근에 말한 이유입니다 ROMAIN GUY : 그리고 여기에 다른 제작자들의리스트가 있습니다 및 플랫폼의 소비자 그래서 우리는 SurfaceView와 SurfaceTexture를 보았습니다 OpenGL ES는 제작자입니다

또한 소비자 일 수도 있습니다 Chet가 그 라이프 사이클에서 어떤 시점에서, 우리는 버퍼를 얻는다 렌더링에서 dequeueBuffer를 호출 할 때입니다 thread로 보내고, 이것은 일반적으로, 우리가 첫 무승부를 할 때 마지막에는 eglSwapBuffer를 호출 할 때 운전자에게 우리가 우리의 프레임을 다 끝냈다는 것을 알리기 위해, 실제로 프레임을 생성합니다

다시 버퍼 큐에 넣으십시오 Vulcan, MediaPlayer, 및 MediaCodec 그리고 우리는 플랫폼 전반에 걸쳐 훨씬 더 많은 것을 가지고 있습니다 자, 실제 작곡 그래서 우리는 여러 창을 만들었습니다

각각 자신의 레이어가 있습니다 SurfaceFlinger는 모든 레이어에 대해 알고 있으며, 그리고 SurfaceFlinger는 실제로 디스플레이와 대화하기 위해 하드웨어 작곡가 (Hardware Composer)라고 불리는 것에 대해 이야기합니다 하드웨어 합성기는 하드웨어 추상화 레이어입니다 우리가 GPU 사용을 피하기 위해 사용하기 때문에 화면에 모든 창을 합성해야합니다 이유 중 하나는 배터리를 절약하는 것입니다

그렇게 효율적으로 전력을 소비합니다 하지만 응용 프로그램에 액세스 권한이 있는지 확인해야합니다 기본적으로 GPU의 모든 기능에 적용됩니다 우리는 당신을 멀리하지 않습니다 그리고 과거에는 들었을 수도 있습니다

창 수를 제한해야한다고 당신이 화면에 넣어 그리고 당신은 왜 몇 슬라이드에서 볼 수 있습니다 그래서 우리는 하드웨어 작곡가가 있습니다 효과적으로 하드웨어 블록입니다 멀티플 비트 맵을 사용하면 정말 빠릅니다

화면에서 함께 구성 할 수 있습니다 그리고 우리는 방금 이것에 대해 이야기했습니다 그래서 실제로 작동하는 방법 – 하드웨어 작곡가 정말 일종의 프로토콜입니다 여기에서는 이전 Hardware Composer에 대해 설명하겠습니다 하드웨어 작곡가 1 또는 하드웨어 작곡가 0이라고합니다

나는 항상 혼란 스럽다 우리는 Hardware Composer 2라는 것을 사용합니다 하지만 훨씬 더 복잡해 그래서 나는 그렇지 않다 여기에서 설명 할 것입니다 그러나 그것의 요지는 기본적으로 같은 방식으로 작동합니다

그래서 SurfaceFlinger는 많은 레이어를 가지고 있습니다 하드웨어 작곡가에서 준비를 할 것입니다 그리고 더 오래된 레이어를 Hardware Composer로 보냅니다 모든 계층에서 무엇을하고 싶은지 알려달라고 요청하십시오 모든 하드웨어 합성기는 독점적 인 조각입니다 사용중인 휴대 전화 또는 태블릿의 하드웨어 정보 우리가 쓸 수있는 방법이 없습니다

모든 다른 하드웨어 작곡가를위한 드라이버 저 밖에 그래서 대신, 하드웨어 작곡가의 그가하고 싶은 것을 우리에게 말해 줄 것입니다 따라서이 경우에는 레이어가 있습니다 하드웨어 작성자가 오버레이로 답장합니다 즉, 하드웨어 작성자가 픽셀 형식을 이해하고 있음을 의미합니다

그 창에 대해 그것을 처리 할 수 ​​있다고 알려줍니다 그리고 그 창문을 위해 작곡을 할 것입니다 그래서 우리는 계속 간다 두 번째 레이어에 오버레이가 표시됩니다 세 번째 레이어를 오버레이한다고 말하고 있습니다

그래서 훌륭합니다 즉, 모든 구성을 자동으로 수행 할 수 있습니다 우리를 대신하여 매우 효율적인 방법으로 이제 우리 지도자들은 모두 오버레이와 일치합니다 우리는 세트라고 부른다 이번에는 모든 레이어를 하드웨어 작곡가에게 보냅니다

실제 작곡을 위해, 그리고 하드웨어 작곡가 모든 것을 화면에 보냅니다 이제는 더 복잡한 예입니다 그래서 우리는 많은 수의 레이어를 가지고 있습니다 우리는 준비라고 부릅니다 처음에는 모든 것이 잘됩니다

하드웨어 작곡가는 오버레이라고 말합니다 그것은 그것을 처리 할 수 ​​있습니다 그러나 어떤 이유로, 다음 하나를 위해, 그것은 말한다, 프레임 버퍼 이렇게하면 픽셀 형식을 사용하는 경우에 발생할 수 있습니다 지원되는 것일 수도 있습니다

회전을 사용하여, 그리고 하드웨어 작곡가 알지 못한다 회전을 처리하는 방법 또는 화면에 너무 많은 레이어 또는 여러 가지 이유 그 하드웨어 작곡가에 특유한 것입니다 CHASE HAASE : 이것은 기기에서 훨씬 더 보편적이었습니다 아마 3 년에서 4 년 또는 그보다 더 오래 전에 그래, 맞아

우리는 약 4 개의 하드웨어 레이어를 사용했습니다 네가 사용할 수있는 네 명이야 5 점입니다 네 명이야 그래서 우리는 4 개를 가지고 있었고, Pixel 2에는, 너무 많은 세부 사항으로 들어가기없이, 당신은 기본적으로 7을 가지고 있습니다

그래서 예전보다 훨씬 나아졌습니다 그러나 Pixel 2 XL을 사용하는 경우 두 개의 레이어를 사용합니다 둥근 모서리를 그립니다 그래서 당신은 실제로 7이 없습니다 너는 5 명이있다

실제로 병합 될 수 있기 때문에 실제로 6 개입니다 하드웨어 작곡가 어쨌든, 많은 세부 사항은 정말 복잡 할 수 있습니다 모든 세부 사항을 알 필요는 없습니다 어쨌든이 경우 우리는 하나의 레이어를 가지고 있습니다

하드웨어 작곡가로 바로 갈 수 있습니다 프레임 버퍼로 표시된 두 개의 레이어가 있습니다 그리고 그것이 우리를 위해 어려운 부분이 시작되는 곳입니다 하드웨어에서 처리하지 않는 레이어가있을 때 작곡가, 우리는 그들을 합성하기 위해 GPU를 사용해야합니다 그래서 SurfaceFlinger는 모든 것을 할 수 있어야합니다

하드웨어가 할 수있는 것 그리고 그 상황에서, 우리는 기본적으로, 스크래치 버퍼 – 다른 레이어 – 우리가 알고있는 형식으로 하드웨어 작곡가 수락 할 수 있습니다 그런 다음 사용자 정의 OpenGL 코드를 사용합니다 그 두 계층의 구성을 스스로 할 수 있습니다 그럼, 일단 우리가 그 부분을 다 끝내면, 우리는 두 개의 레이어 만 남았고 우리는 그것들이 Hardware Composer로 보내질 수 있다는 것을 알아라

그래서 그것이 우리가하는 일입니다 우리는 set을 호출 한 다음 화면에 표시합니다 CHET HAASE : 그럼 언젠가 호기심이 생기면, 이 명령은 adb shell dumpsys SurfaceFlinger 명령을 실행할 수 있습니다 ROMAIN GUY : 자본금 S, 자본금 F CHET HAASE : 매우 중요합니다

그리고 그것은 당신이 원하는 것보다 더 많은 정보를 얻게 될 것입니다 그러나 그것이 당신에게 보여줄 것 중 하나 화면의 창에 대한 테이블입니다 현재 그들이 대표되고 있는지 여부 오버레이 또는 프레임 버퍼로 ROMAIN GUY :이 명령을 꽤 실행해야하지만 내부적으로 수많은 최적화가 있기 때문에 신속하게 처리 할 수 ​​있습니다 따라서 레이어가 잠시 동안 화면에 있었다

우리는 그들이 변화하지 않는다는 것을 알고 있습니다 그들의 하드웨어 작곡가가 그들을 붕괴시키고 있을지 모른다 다시 바뀔 때까지 단일 레이어로 그래서 그 명령의 출력은 때로는 조금 있습니다 오해의 소지가 있습니다 결과를 볼 수도 있기 때문입니다

시간에 기반한 최적화 따라서 가장 좋은 방법은 일반적으로이 작업을 실행하는 것입니다 애니메이션이나 무언가를 운영 할 때 화면에서 변경 중입니다 그것은 당신에게 가장 가치있는 정보가 될 것입니다 그래서 우리가 이야기하지 않은 몇 가지 다른 것들

텍스트를 무효화하는 변형을 사용하라고 알려 왔습니다 직사각형 뷰의 일부만 무효화 할 수 있습니다 당신이 다시 칠해야 할 필요가 있음을 알았습니다 이는 구형 Android 기기에서 특히 중요했습니다

대역폭이 극도로 제한 되었기 때문입니다 우리는 소프트웨어 렌더링을 사용하고있었습니다 그리고 우리를위한 GPU 렌더링의 초창기에도, 우리는 꽤 쉽게 GPU를 맥 아웃했다 그래서 그것들은 정말로 중요한 저축이었습니다 더 이상이 작업을 수행 할 필요가 없습니다

심지어 최신 버전의 Android에서도 이 기능이 사용 중지되기 전에 실제로는 시스템에서 무시됩니다 이제 어떻게 될까요? 무효화하거나 무효화 할 때마다 뷰에 직사각형이있는 경우 렌더링 스레드의 전체보기를 재검토하려고합니다 그 유일한 손상된 지역을 재 계산하십시오 그것에 대해 걱정할 필요가 없습니다 그리고 우리가 제거하고있는 이유 중 하나 저축을 위해 더 이상 필요하지 않을뿐만 아니라, 하지만 오류가 발생하기 쉽기 때문입니다

한 번에 하나씩 오류나 반올림하는 것이 쉽습니다 오류 및 화면에 아티팩트를 가져올 수 있습니다 그리고 쳇과 나는 그걸 증명할 수있어 우리가 너무 많은 버그를 링크 시켰기 때문에 API 사용 그리고 프레임 워크 자체에는 여전히 버그가 있습니다 그 주위에

이제는 걱정할 필요가 없습니다 RecyclerView는 이제 프리 페치를 수행 할 수 있습니다 항목의 미리 CHASE HAASE : 예, 우리는 이것을 일찍 언급했습니다 이것은 우리가 지금 나가고있는 승리 중 하나입니다

때문에 별도의 렌더링 스레드를 가지고, 지금, 음, 유휴 시간이 있어요 UI 스레드는 동기화 된 후에 작업이 완료되었습니다 음, 유휴 시간을 생산적으로 사용할 수 있습니다 물건을 가져 오는 것과 같은 다른 일을 할 때 그것은 다음 몇 프레임에서 필요할지도 모른다는 것을 알고 있습니다 로망 가이 : 작곡을 위해서, 내부적으로, 우리는 실제 디스플레이의 개념을 가지고 있습니다

이것은 사용할 수있는 API입니다 예를 들어, 그게 우리가 스크린 샷을 찍을 때 사용하는 것입니다 또는 비디오를 녹음 할 때 또는 우리가 캐스팅 할 때 – 예를 들어 Chromecasting 우리가 효과적으로하는 것은 SurfaceFlinger에게 컴포지션을 수행하지만 직접 표시하지는 않습니다 다른 표면으로

그래서 이것은 표면을 만드는 또 다른 방법입니다 관심이 있으시면 훌륭한 샘플 애플리케이션이 있습니다 GitHub에서 K를 사용할 수있는 Graphika가 있습니다 그것은 그래픽 회원이 썼다 몇 년 전에 팀에

그것은 기본적으로 모든 것을 모아 놓은 것입니다 당신은 SurfaceFlinger, Surface, 미디어 인코더가있는 SurfaceView와 가상 디스플레이가 결합되어 있습니다 이 코드는 매우 흥미로운 코드입니다 색상 변환 Android O에서는 색상 관리, 이것이 우리가 적용 할 수있는 색 변환 중 하나입니다

야간 조명과 같은 것들도 색상 변환입니다 우리는 또한 색맹 시뮬레이션을합니다 그것들은 하드웨어에 의해 처리 될 수 있습니다 특정 상황에서 작곡가, 그리고 그들은 성능 문제의 원인이 될 수 있습니다 예를 들어 잠시 후, 야간 조명 N5X 또는 N6B에서 지원되지 않았습니다

이유 중 하나는 하드웨어였습니다 우리는 색 변환을 할 수있는 드라이버가 없었습니다 그래서 우리는 GPU 구성으로 돌아 가야했습니다 정말 비쌌습니다 배터리를 아프게 했으므로 장치에 기능이 있습니다

그리고 Chet가 말했듯이, 더 많은 세부 사항들이 많이 있습니다 렌더링 파이프 라인에 대해 이것은 단지 매우 높은 수준의 개요였습니다 우리는 과거에 많은 회담을 가졌습니다 더 자세히 설명하는 우리는 예를 들어, UI 렌더링 자체에서, 일괄 처리 및 병합을 어떻게 처리할까요? 그런 종류의 최적화 그래서 당신이 관심이 있다면, 당신은 그들을 참조 할 수 있습니다

그림자 계산은 흥미 롭습니다 나는 우리가 우리가 이야기 한 이야기가 있었다고 생각한다 그 세부 사항의 그러나 렌더링 파이프 라인에 정확히 어디에서 적합합니까? 일종의 영리합니다 그러나 그렇다

더 많이 거기에서 계속하고있다 그러나 잘만되면, 이것은 Android에서 어떻게 작동하는지 일반적인 감각을 제공합니다 ROMAIN GUY : 그걸로 끝났습니다 우리가 거기 멈출거야 고맙습니다

[박수 갈채] [음악 재생]