2. 1.Surfaceflinger 서비스 구조
서비스 클라이언트 서비스 프록시 시스템 서비스
SurfaceComposer
ISurfaceComposer SurfaceFlinger
Client
ISurfaceComposer
SurfaceControl
Client
리모트 서비스
ComposerService IGraphicAlloc
Client
Compser ISurface
Surface GraphicBufferAlloc
ISurfaceTexture
SurfaceTextureClient BufferQueue
2
3. 1.Surfaceflinger 서비스 구조-서비스 클라이언트
서비스 클라이언트
구성요소 설명
SurfaceComposeClient 1.서피스 플링거 서비스와 연결
2. 서피스 생성,삭제, 상태변경 요청
SurfaceControl 1.레이어마다 하나의 SurfaceControl 객체가 생성 됨.
2. SurfaceComposeClient 의 상태 변경 함수를 매핑하여 사용 함.
ComposerService 1.애플리케이션이 서피스 플링거와 연결 시 서피스 플링거 서비스의 서비스 프록시
(ISurfaceComposer)를 획득 함.
2.디스플레이 공유 메모리의 서비스 프록시 획득
Composer 1. SurfaceComposeClient에서 레이어의 상태 변경 요청 시 Composer 클래스의
함수 사용
Surface(c++) 1.SurfaceTextureClient를 상속 받음.
2. 서피스의 네이티브 윈도우를 사용 할 수 있도록 도와줌.
SurfaceTextureClient 1.안드로이드 네이티브 윈도우의 그래픽 버퍼를 사용하기 위한 멤버 함수를 가짐.
3
4. 1.Surfaceflinger 서비스 구조-시스템/리모트 서비스
시스템 서비스 /리모트 서비스
구성요소 서비스 프록시 설명
SurfaceFlinger ISurfaceComposer 1.서피스 생성,삭제
2.레이어 합성
Client ISurfaceComposerClient 1.생성된 레이어를 Client 별로 관리
BufferQueue ISurfaceTexture 1.그래픽 버퍼 생성
2.레이어 하나 당 하나의 버퍼 큐 리모트 서비스가 생성 됨.
GraphicBufferAlloc IGraphicBufferAlloc 1. 그래픽 버퍼 생성 후 메모리 할당 요청이 발생하면
graphic HAL에게 메모리 할당 요청
4
5. 2.Surfaceflinger 서비스 아키텍처
서비스 클라이언트 SurfaceFlinger
Client 1
2
ANativeWindow Refbas
3 dequeue surfacetexture
e
SurfaceControl BufferQueue 4 그래픽버퍼
queue layer1
2
5
surfacetextureclient
layer2
합성
OpenGL
surface layer3 ES API
1 서피스 플링거와 연결이 되면 서피스를 관리하는 Client 리모트 서비스가 생성된다.
2 서피스 (layer)생성이 되면 서버측에는 surfacetexture가 생성되고, 클라이언트에는 surfacetextureclient가 생성된다.
3 어플리케이션은 surfacetextureclient를 이용하여 그래픽 버퍼의 요청(dequeue), 출력요청(queue) 할 수 있다.
4 애플리케이션 측에서 그래픽 버퍼 요청이 발생하면 SurfaceTexture는 GraphicBufferAlloc 리모트 서비스에게 그래픽
메모리를 요청하여 할당 받는다. (그래픽 버퍼 할당)
5 서피스 출력 요청이 발생 되면 Surfaceflinger는 각 그래픽 버퍼를 OpenGL ES API를 사용하여 합성한다.
서피스 출력 모드:동기,비동기
-동기:출력 요청이 발생한 버퍼의 인덱스를 mQueue 변수에 차례로 저장하고, 서피스 플링거 서비스의 합성을 요청 함.
-비동기:mQueue 변수의 첫번째 인덱스에 저장하고, 서피스 플링거 서비스의 합성을 요청 함.
5
7. 3.SurfaceFlinger 클래스의 인스턴스 생성-ICS 이후
System_init.cpp
extern "C" status_t system_init()
{
if (strcmp(propBuf, "1") == 0) { init.rc에 다음과 같이 정의 되어서 system init에서 surfaceflinger를 실행하지 않음
// Start the SurfaceFlinger
SurfaceFlinger::instantiate(); # Set this property so surfaceflinger is not started by system_init
}} setprop system_init.startsurfaceflinger 0
Init.rc(systemcorerootdir)
service servicemanager /system/bin/servicemanager
class core
user system
group system
critical
onrestart restart zygote
onrestart restart media
onrestart restart surfaceflinger zygote를 실행하면서 surfaceflinger를 독립 프로세스로 실행 시킴.
onrestart restart drm
Main_surfaceFlinger.cpp
int main(int argc, char** argv) {
SurfaceFlinger::publishAndJoinThreadPool(true);
return 0;
}
7
8. 3.SurfaceFlinger 클래스의 인스턴스 생성
Pthread_create
2 3
Thread
Run() _threadLoop()
Refbase
4 1회호출 5 반복호출
1
SurfaceFlinger
onFirstRef() ReadyToRun() ThreadLoop()
RefBase.cpp
void RefBase::incStrong(const void* id) const{
const_cast<RefBase*>(this)->onFirstRef();
}
SurfaceFlinger..cpp
void SurfaceFlinger::onFirstRef()
{ mEventQueue.init(this); 서피스 플링거 서비스가 사용할 네이티브 루퍼와 핸들러를 생성한다.
run("SurfaceFlinger", PRIORITY_URGENT_DISPLAY);
1 // Wait for the main thread to be done with its initialization
mReadyToRunBarrier.wait(); ReadyToRun 함수에서 mReadyToRunBarrier.open()가 불릴때 까지 기다린다.
}
8
9. 3.SurfaceFlinger 클래스의 인스턴스 생성
Threads.cpp
status_t Thread::run(const char* name, int32_t priority, size_t stack){
res = androidCreateRawThreadEtc
(_threadLoop,this, name, priority, stack, &mThread);
}
2
int androidCreateRawThreadEtc(){
int result = pthread_create(&thread, &attr,
(android_pthread_entry)entryFunction, userData);
} 3
int Thread::_threadLoop(void* user)
{
do {
bool result;
if (first) {
first = false;
self->mStatus = self->readyToRun(); 4
}
else{
result = self->threadLoop(); 5
}
}
}
9
10. 3.SurfaceFlinger 클래스의 인스턴스 생성-readyToRun()
SurfacefFlinger.cpp
status_t SurfaceFlinger::readyToRun()
(
1.메인 디스 플레이 초기화
// initialize the main display
GraphicPlane& plane(graphicPlane(dpy));
DisplayHardware* const hw = new DisplayHardware(this, dpy);
plane.setDisplayHardware(hw);
2. 디스 플레이 공유 메모리 생성
// create the shared control-block
mServerHeap = new MemoryHeapBase(4096, MemoryHeapBase::READ_ONLY, "SurfaceFlinger read-only heap");
mServerCblk = static_cast<surface_flinger_cblk_t*>(mServerHeap->getBase());
new(mServerCblk) surface_flinger_cblk_t;
3. initialize the shared control block
mServerCblk->connected |= 1<<dpy;
display_cblk_t* dcblk = mServerCblk->displays + dpy;
memset(dcblk, 0, sizeof(display_cblk_t));
4.open GL ES 초기화
// Initialize OpenGL|ES
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
glPixelStorei(GL_PACK_ALIGNMENT, 4);
glEnableClientState(GL_VERTEX_ARRAY);
5.이벤트 쓰레드 생성:이벤트 쓰레드를 생성하여 하드웨어 컴포저에서 발생한 Vsync 이벤트를 전파한다.
mEventThread = new EventThread(this);
mEventQueue.setEventThread(mEventThread);
hw.startSleepManagement();
6.onfirstref()에서 기다리고 있는 thread에 signal 보냄.
mReadyToRunBarrier.open();
7.부트 애니메이션 시작
startBootAnim();
}
10
12. 3.메인 디스플레이 초기화
2. DisplayHardware* const hw = new DisplayHardware(this, dpy);
DisplayHardware를 생성
(전원 on/off 이벤트 처리 쓰레드 생성, EGL Native 윈도우 생성, EGL 초기화 수행)
1.전원 버튼 이벤트 처리 쓰레드 생성
:서피스 플링거 서비스는 디스플레이가 켜져 있을 시에만 합성을 수행 함.
디스 플레이의 전원 상태를 감시하고 통지해 주는 displayEventThread를 생성하고 처리 함.
DisplayHardwareBase::DisplayHardwareBase(const sp<SurfaceFlinger>& flinger,
uint32_t displayIndex)
{
mScreenAcquired = true;
mDisplayEventThread = new DisplayEventThread(flinger);
}
Thread
DisplayHardwarebase DisplayEventThread
New
DisplayHardware
Init()
12
13. 3.메인 디스플레이 초기화
2. EGL Native 윈도우 생성
:안드로이드는 프레임 버퍼를 추상화한 FramebufferNativeWindow class를 제공 함.
DisplayHardware::DisplayHardware(..): DisplayHardwareBase(flinger, dpy),mFlinger(flinger), mFlags(0), mHwc(0)
{
init(dpy);
}
void DisplayHardware::init(uint32_t dpy)
{
1. 프레임 버퍼 HAL 생성
mNativeWindow = new FramebufferNativeWindow();
}
FramebufferNativeWindow::FramebufferNativeWindow()
{
if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module) == 0)
{ gralloc.xxx.so 를 load해서, gralloc_module_t(module) 구조체를 획득한다.
-gralloc_module_t 구조체의 주요 함수
함수명 역활 사용자
registerbuffer 그래픽 버퍼를 gralloc HAL에 등록 GraphicBufferMapper사용자
unregisterbuffer 버퍼 등록 해지
lock 그래픽 버퍼에 할당된 메모리의
가상주소 획득
unlock 가상주소에 렌더링이 완료됨을 알림
13
14. 3.메인 디스플레이 초기화
err = framebuffer_open(module, &fbDev);
framebuffer device를 open하고 반환된 framebuffer_device_t 구조체의 포인터를 fbDev에 저장한다.
(fbDev는 이제 벤더에서 제공하는 라이브러리 함수를 사용할 수 있다.)
Hardware/libhardware/include/hardware/fb.h
static inline int framebuffer_open(const struct hw_module_t* module,
struct framebuffer_device_t** device) {
return module->methods->open(module,
GRALLOC_HARDWARE_FB0, (struct hw_device_t**)device);
} "fb0"
err = gralloc_open(module, &grDev);
그래픽 버퍼 할당 device를 open하고 반환된 alloc_device_t 구조체의 포인터를 grDev에 저장한다.
Hardware/libhardware/include/hardware/gralloc.h
static inline int gralloc_open(const struct hw_module_t* module,
struct alloc_device_t** device) {
return module->methods->open(module,
GRALLOC_HARDWARE_GPU0, (struct hw_device_t**)device);
} “gpu0”
14
15. 3.메인 디스플레이 초기화
프레임 버퍼 생성
for (i = 0; i < mNumBuffers; i++)
{
buffers[i] = new NativeBuffer(
fbDev->width, fbDev->height, fbDev->format, GRALLOC_USAGE_HW_FB);
}
EGL에서 렌더링에 사용할 프런트 버퍼와 백 버퍼를 NativeBuffer 타입의 버퍼로 생성 한다.
GRALLOC_USAGE_HW_FB 는 NativeBuffer 타입의 버퍼가 프레임 버퍼에 매핑되어 있다는 것을 의미함.
for (i = 0; i < mNumBuffers; i++)
{
err = grDev->alloc(grDev,
fbDev->width, fbDev->height, fbDev->format,
GRALLOC_USAGE_HW_FB, &buffers[i]->handle, &buffers[i]->stride);
}
Nativebuffer 와 mapping된 framebuffer에 메모리를 할당한다.
(buffer의 handle이 할당된 메모리를 가리키게 된다(&buffers[i]->handle))
const_cast<uint32_t&>(ANativeWindow::flags) = fbDev->flags;
const_cast<float&>(ANativeWindow::xdpi) = fbDev->xdpi;
const_cast<float&>(ANativeWindow::ydpi) = fbDev->ydpi;
프레임 버퍼 정보를 FramebufferANativeWindow 클래스의 부모인 ANativeWindow 구조체에 저당한다.
이후, 디스플레이 공유 메모리에는 ANativeWindow 에 저장된 프레임 버퍼 정보들이 저장된다.
ANativeWindow::setSwapInterval = setSwapInterval; int FramebufferNativeWindow::lockBuffer(..){
ANativeWindow::dequeueBuffer = dequeueBuffer; framebuffer_device_t* fb = self->fbDev;
ANativeWindow::lockBuffer = lockBuffer; fb-> lockBuffer(fb, index);
ANativeWindow::queueBuffer = queueBuffer; }
…
ANativeWindow method와 framebuffer method를 mapping한다.
(ANativeWindow Type의 surface에서 lockbuffer를 호출하면, FramebufferNativeWindow 의 lockbuffer가 호출된다.)
15
16. 3.메인 디스플레이 초기화
SurfaceFlinger
*EGL ANativeWindow
OpenGL ES
FramebufferNativeWindow
API
NativeBuffer
Front buffer
NativeBuffer
back buffer
Android mapping
kernel
FrameBuffer
Front buffer
back buffer
16
17. 3.메인 디스플레이 초기화
3. EGL 초기 화
:Open GL ES와 Native system 사이의 interface를 제공 함.
void DisplayHardware::init(uint32_t dpy)
{
…
1)EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
기본 디스플레이 정보를 획득 한다.
2)eglInitialize(display, NULL, NULL);
EGL 내부 적으로 사용하는 구조체를 초기화 한다.
3)eglGetConfigs(display, NULL, 0, &numConfigs);
eglGetDisplay에서 전달 받은 display의 사용 가능한 config 개수를 획득한다.
4) eglChooseConfig(dpy, attrs, configs, numConfigs, &n);
사용자가 지정하는 속성에 부합하는 surface를 생성하기 위한 config정보를 설정한다.
5) eglCreateWindowSurface(display, config, mNativeWindow.get(), NULL);
화면에 표시될 네이티브 윈도우를 생성한다. 이때 framebufferNativeWindow의 객체를 넘겨 준다.
6) eglCreateContext(display, config, NULL, contextAttributes);
렌더링에 필요한 상태를 저장할 컨텍스트를 생성한다.
7) eglMakeCurrent(display, surface, surface, context);
현재 렌더링 쓰레드에 사용할 컨텍스트와 display,config 정보 등을 바인드 한다.
…
}
17