SlideShare una empresa de Scribd logo
1 de 15
SurfaceFlingerService
(서피스 출력 요청-JB)




                            박철희

                        1
1.노말 서피스 출력(서비스 클라이언트)

그래픽 버퍼의 가상 주소를 획득한 후 그래픽 버퍼의 메모리에 랜더링 하여 서피스 플링거로 출력 요청하게 된다.

 노말 서피스의 출력 요청 과정




SurfaceTextureClient의 queueBuffer함수는 서피스 플링거에게 출력할 버퍼를 알려준다.
int SurfaceTextureClient::queueBuffer(android_native_buffer_t* buffer) {
     timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
     해당 버퍼의 마지막 출력 요청 시간.
     int i = getSlotFromBufferLocked(buffer);
     출력 요청할 버퍼의 인덱스를 검색한다.

      ISurfaceTexture::QueueBufferOutput output;
     ISurfaceTexture::QueueBufferInput input(timestamp, crop, mScalingMode, mTransform);
    status_t err = mSurfaceTexture->queueBuffer(i, input, &output);
    BufferQueue의 queueBuffer를 호출한다.
       ( i : 출력할 버퍼 인덱스, input(timestamp:해당 버퍼의 출력 요청 시간등),
        output:서버에 저장된 그래픽 버퍼의 가로,세로 값을 저장함. 이 값은 애플리케이션에서 다음 그래픽 버퍼 획득 시
        기본 값으로 사용 됨.)
}
                                                                                   2
2.노말 서피스 출력(서비스 서버)

출력 방식은 동기, 비동기 2가지의 경우가 있다.
1.동기식:애플리케이션에서 출력 요청이 한번 발생하면 서피스 플링거 서비스에서도 한번의 출력이 발생 됨.
2.비동기식:출력 요청이 발생한 횟수에 관계없이 서피스 플링거 서비스의 합성에 맞추어 화면 출력이 됨.
status_t BufferQueue::queueBuffer(int buf, const QueueBufferInput& input, QueueBufferOutput* output) {

     if (mSynchronousMode) {  동기식일 경우
          mQueue.push_back(buf);  출력 대기 큐의 제일 마지막에 넣는다.(FIFO 방식)
          listener = mConsumerListener;
          mConsumerListener 는 SurfaceTexture 생성자에서 BufferQueue::ProxyConsumerListener 로 설정되어 있음.
          이 lister는 출력 가능한 버퍼가 대기 하고 있다는 것을 서피스 플링거에게 알려줌.
    }
    else 비동기식
    {
             if (mQueue.empty()) 출력 대기 큐에 대기하는 버퍼가 없다면
             {
               mQueue.push_back(buf);  현재 요청된 버퍼를 대기 큐에 저장함.
               listener = mConsumerListener;
              }
            else {  출력 대기 하고 있는 버퍼가 있다면
            Fifo::iterator front(mQueue.begin()); 출력 대기 큐의 첫번째 인덱스를 획득해서,
            mSlots[*front].mBufferState = BufferSlot::FREE; 슬롯의 상태를 FREE로 만든다.
            *front = buf;  출력 대기 큐의 첫번째 인덱스에 새롭게 요청한 인덱스를 넣는다.
          }
         mSlots[buf].mBufferState = BufferSlot::QUEUED;  버퍼의 상태를 QUEUED로 바꿈.
          즉, 클라이언트는 출력 요청 하였고,서피스 플링거 서비스는 해당 버퍼를 아직 합성하지 않았다는 의미 임.
        mDequeueCondition.broadcast();  FREE상태를 기다리는 dequeueBuffer 함수를 깨운다.
        if (listener != 0) {
                  listener->onFrameAvailable(); 서피스 플링거에게 합성 신호를 보내게 요청 함.
           }


                                                                                                         3
2.노말 서피스 출력(서비스 서버)

void BufferQueue::ProxyConsumerListener::onFrameAvailable() {
  sp<BufferQueue::ConsumerListener> listener(mConsumerListener.promote());
  if (listener != NULL) {
      listener->onFrameAvailable();
  }
}                         SurfaceTexture는 BufferQueue::ConsumerListener 를 상속 받기 때문에
                       SurfaceTexture::onFrameAvailable가 호출 된다.


SurfaceTexture.cpp
void SurfaceTexture::onFrameAvailable() {

  if (listener != NULL) {
      ST_LOGV("actually calling onFrameAvailable");
      listener->onFrameAvailable();
  }
}
Layer.cpp
struct FrameQueuedListener : public SurfaceTexture::FrameAvailableListener {
     FrameQueuedListener(Layer* layer) : mLayer(layer) { }
      virtual void onFrameAvailable() {
           if (that != 0) {
             that->onFrameQueued();
         }
     }};

void Layer::onFrameQueued() {
  android_atomic_inc(&mQueuedFrames);  mQueuedFrames는 출력 요청이 발생한 횟수를 저장함.
  mFlinger->signalLayerUpdate(); 서피스 플링거에게 합성 시그널을 보냄.
}


                                                                                      4
3.디스플레이 이벤트 동기화

젤리빈부터 하드웨어에서 발생하는 Vsync 이벤트에 맞춰 렌더링을 시작하도록 변경 됨.
서피스 플링거 역시 Vsync 에 맞춰 합성을 시작 함.
Vsync Event
1.연속적 통지: Vsync 이벤트 발생 시 마다 이벤트 통지
2. 일회성 통지: Vsync 이벤트 요청 시 마다 이벤트 통지
서피스 플링거는 일회성 통지를 사용, 즉 출력 버퍼 큐에 새로운 버퍼가 추가되면 Vsync 에 맞춰 합성 시그널이 발생됨.


SurfaceFlinger.cpp
void SurfaceFlinger::signalLayerUpdate() {
    mEventQueue.invalidate();
}

Messagequeue.cpp
void MessageQueue::invalidate() {
   mEvents->requestNextVsync();
    mEvents 는 EventThread 의 Connection class를 가르킨다.
}

EventThread.cpp
void EventThread::Connection::requestNextVsync() {
  mEventThread->requestNextVsync(this);  mEventThread 는 EventThread를 가르킨다.
}

void EventThread::requestNextVsync( const sp<EventThread::Connection>& connection) {
   if (connection->count < 0) {  count의 초기 값이 -1이다.
      connection->count = 0;  count 값이 0 이면 일회성 통지를 의미함.
      mCondition.broadcast();  EventThread::threadLoop() 에서 기다리는 thread를 깨움.
  }
}

                                                                                       5
3.디스플레이 이벤트 동기화
 EventThread::threadLoop() 에서 Vsync가 발생 할때 까지 대기 하다 mCondition.broadcast(); 가 불리면 깨어 난다.
bool EventThread::threadLoop() {
do {
      do {
        timestamp = mVSyncTimestamp;
         mVSyncTimestamp는 HWComposer로 부터 Vsync가 전달되면 갱신된다.
         즉, HWComposer 로 부터 전달된 Vsync로 깨어난 경우가 아니라면, mVSyncTimestamp 은 0 이다.
         현재 경우는, requestNextVsync 에 의해 깨어 났기 때문에 mVSyncTimestamp 가 0 이다.
        mVSyncTimestamp = 0;

     bool waitForNextVsync = false;
     size_t count = mDisplayEventConnections.size(); VSync 이벤트를 기다리는 수신자들(서피스 플링거)을 획득한다.
     for (size_t i=0 ; i<count ; i++) {
        sp<Connection> connection =mDisplayEventConnections.itemAt(i).promote();
        connectionList.add(connection);
        if (connection!=0 && connection->count >= 0) {
            EventThread::requestNextVsync 에서 count 값을 0으로 설정했다. 이 의미는 Vsync 를 받아 출력해야 할
              Event가 있다는 의미이다.
            waitForNextVsync = true;
            Vsync가 필요하다는 의미로 waitForNextVsync 를 설정 한다.
            break;
        }

      if (timestamp) {  timestamp 가 0 보다 크다는 것은 HWComposer 로 부터 Vsync가 발생 되었다는 의미이다.
                      현재 경우는 Vsync가 전달되지 않았기 때문에 0 이다.
         if (!waitForNextVsync) {
         } else {
             이 경우는 HWComposer 로 부터 Vsync가 발생된 경우임으로 첫번째 do while문을 빠져 나간다.
             break;
         }
     }

                                                                                     6
3.디스플레이 이벤트 동기화
      else {  HWComposer 로 부터 Vsync 가 발생 되지 않을 경우
         if (waitForNextVsync) {  Vsync가 필요 함으로
           enableVSyncLocked();  HWCompser에게 Vsync 발생 요청
       }

        mCondition.wait(mLock);  HWCompser로 부터 Vsync 가 발생되기를 기다림.
  } while(true); // 첫번째 do while문

 const size_t count = mDisplayEventConnections.size();  이벤트 쓰레드에 등록된 Vsync 이벤트 수신자를 획득한다.

 for (size_t i=0 ; i<count ; i++) {
  const int32_t count = connection->count;
             if (count >= 1) {
             reportVsync = true;  수신자의 모드가 연속(count =1) 일 경우 reportVsync 를 수신 할 수 있다.
             } else if (count >= -1) {
             If (count == 0) {
                  reportVsync = true; 수신자의 모드가 일회성(count =0) 일 경우 reportVsync 를 수신 할 수 있다.
             }
             if (reportVsync) {
                   displayEventConnections.add(connection);
                    Vsync를 수신 받을 수신자를 displayEventConnections 에 추가한다.
             }
 }
 while (!displayEventConnections.size());  Vsync를 수신 받을 수신자가 있기 때문에 두번째 do while 문을 벗어난다.

 vsync.header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC; 수신자에게 보낼 이벤트 타입 설정
 vsync.header.timestamp = timestamp;  Vsync 발생 시간

 const size_t count = displayEventConnections.size();  Vsync를 수신 받을 수신자의 개수를 가져온다.
 for (size_t i=0 ; i<count ; i++) {
         status_t err = conn->postEvent(vsync);  각 수신자에게 Vsync를 보낸다.
  }
                                                                                      7
3.디스플레이 이벤트 동기화
 Vsync 수신시의 처리
 애플리케이션 측에서는 choreographer class를 이용하면 Vsync 이벤트를 수신 할 수 있다.
 서피스 플링거는 네이티브 루퍼에서 Vsync event를 수신한다.
 네이티브 루퍼는 Vsync가 수신되면 MessageQueue::setEventThread 의 MessageQueue::cb_eventReceiver 가 불려진다.

MessageQueue.cpp
void MessageQueue::setEventThread(const sp<EventThread>& eventThread)
{
  mEventThread = eventThread;
  mEvents = eventThread->createEventConnection();
  mEventTube = mEvents->getDataChannel();
  mLooper->addFd(mEventTube->getFd(), 0, ALOOPER_EVENT_INPUT, MessageQueue::cb_eventReceiver, this);
}


int MessageQueue::cb_eventReceiver(int fd, int events, void* data) {
   MessageQueue* queue = reinterpret_cast<MessageQueue *>(data);
   return queue->eventReceiver(fd, events);
}

int MessageQueue::eventReceiver(int fd, int events) {
     while ((n = DisplayEventReceiver::getEvents(mEventTube, buffer, 8)) > 0) {
      for (int i=0 ; i<n ; i++) {
         if (buffer[i].header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {
             mHandler->signalRefresh();  MessageQueue::Handler::signalRefresh 를 호출한다.
             break;
         }
      }
   }



                                                                                                8
3.디스플레이 이벤트 동기화
void MessageQueue::Handler::signalRefresh() {
   if ((android_atomic_or(eventMaskRefresh, &mEventMask) & eventMaskRefresh) == 0) {
      mQueue.mLooper->sendMessage(this, Message(MessageQueue::REFRESH));
     네이티브 루퍼에 MessageQueue::REFRESH 를 보낸다.
  }
}


void MessageQueue::Handler::handleMessage(const Message& message) {
  case REFRESH:
       android_atomic_and(~eventMaskRefresh, &mEventMask);
       mQueue.mFlinger->onMessageReceived(message.what);
       Surfaceflinger의 onMessageReceived 를 호출한다.
       break;
  }
}




                                                                                       9
4.레이어 합성과 화면 출력
Surfaceflinger의 onMessageReceived 함수는 화면 출력 준비가 된 레이어들을 모아서 합성한 후 프레임 버퍼에 출력한다.

void SurfaceFlinger::onMessageReceived(int32_t what)
{
  switch (what) {
     case MessageQueue::INVALIDATE:
     case MessageQueue::REFRESH: {
        ….
        handlePageFlip(); 레이어에 할당된 그래픽 버퍼를 EGL Image로 만들어 텍스쳐로 사용할 수 있도록 만든다.---(1)
        handleRepaint();합성
        hw.compositionComplete(); 합성이 완료 되었다는 것을 하드웨어에게 알려줌.
         postFramebuffer();  완료된 합성 이미지를 프레임 버퍼에 출력.------------(2)
}

(1) handlePageFlip
void SurfaceFlinger::handlePageFlip()
{
     const bool visibleRegions = lockPageFlip(currentLayers);
}

bool SurfaceFlinger::lockPageFlip(const LayerVector& currentLayers)
{
   layer->lockPageFlip(recomputeVisibleRegions);
}

Layer.cpp
void Layer::lockPageFlip(bool& recomputeVisibleRegions)
{
  if (mSurfaceTexture->updateTexImage(&r) < NO_ERROR) {
      return;
}
                                                                            10
3.레이어 합성과 화면 출력
status_t SurfaceTexture::updateTexImage(BufferRejecter* rejecter) {

   err = mBufferQueue->acquireBuffer(&item);  출력 대기 큐의 첫번째 요소에 저장된 버퍼를 획득한다.


   BufferQueue.cpp
   status_t BufferQueue::acquireBuffer(BufferItem *buffer)
   {
      if (!mQueue.empty()) {
     Fifo::iterator front(mQueue.begin());
     int buf = *front; 출력 대기 큐의 첫번째 인덱스를 가져온다.

       buffer->mGraphicBuffer = mSlots[buf].mGraphicBuffer; 그래픽 버퍼를 변수에 저장.
       buffer->mTimestamp = mSlots[buf].mTimestamp;  버퍼의 출력 요청 시간 저장.

       mSlots[buf].mBufferState = BufferSlot::ACQUIRED;
        버퍼 상태를 ACQUIRED 로 바꾸어서, 다시 queuebuffer 할 수 없도록 함.

       mQueue.erase(front);  다음 버퍼를 위해 출력 대기 큐에서 삭제.
   }

    if (item.mGraphicBuffer != NULL) {  획득한 버퍼 인덱스의 GraphicBuffer 가 있으면
         mEGLSlots[buf].mGraphicBuffer = 0;  기존 mEGLSlots 의 내용을 지운다.
         if (mEGLSlots[buf].mEglImage != EGL_NO_IMAGE_KHR) {
             eglDestroyImageKHR(dpy, mEGLSlots[buf].mEglImage);
             mEGLSlots[buf].mEglImage = EGL_NO_IMAGE_KHR;
         }
         mEGLSlots[buf].mGraphicBuffer = item.mGraphicBuffer;  GraphicBuffer 다시 지정.
     }

       image = createImage(dpy, mEGLSlots[buf].mGraphicBuffer);  EGL Image를 다시 만든다.
       mEGLSlots[buf].mEglImage = image;  만든 EGL Image를 mEGLSlots에 저장한다.
                                                                                       11
3.레이어 합성과 화면 출력
glEGLImageTargetTexture2DOES(mTexTarget, (GLeglImageOES)image);
바인딩된 텍스쳐에 대한 소스를 생성한 EGL Image로 지정 한다.
 (즉, 어떤 EGL Image를 사용할지 결정 함.)




if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
          status_t status = mBufferQueue->releaseBuffer(mCurrentTexture, dpy,  이전 버퍼를 release한다.
                        mEGLSlots[mCurrentTexture].mFence);
}
    BufferQueue.cpp
    status_t BufferQueue::releaseBuffer(int buf, EGLDisplay display,EGLSyncKHR fence) {
      if (mSlots[buf].mBufferState == BufferSlot::ACQUIRED) {
       mSlots[buf].mBufferState = BufferSlot::FREE; status를 FREE 로 만들고
      }
     mDequeueCondition.broadcast();  FREE 인 버퍼가 있음을 broadcast한다.
    }

mCurrentTexture = buf;  현재 index를 mCurrentTexture 에 저장 한다.
mCurrentTextureBuf = mEGLSlots[buf].mGraphicBuffer;
}
                                                                                                    12
3.화면 출력 시 Buffer status 변경

                                                                                      BufferQueue::releaseBuffe에 의해
                                                                                7     mslot의 4번 status가 FREE로 변경됨.


                                                           mSlot

출력 대기 큐에서                                           [0]
4번 인덱스를                     mQueue의 첫번 째 요소의
삭제       mQueue     1       mSlot의 status를 FREE로 만든다.
   4                                                [1]
       [0]   2->4                   X               [2]                 F      D->F
                                                                                      EGL Image
       [1]                                          [3]                                               5
                        2     출력할 버퍼의 인덱스를
                              mQueue의 처음에 넣는다.                          A             그래픽 버퍼              출력할 그래픽 버퍼를
       [2]                                          [4]
                                                                                                          EGL Image로 만든다.
                                                                        D->A
                                                                       acquireBuffer에 의해
                                                                   3   Status 를
                                                                       ACQUIRED로 변경함

                                                           mEGLSlots

                                                     [0]                                     6
                                                                                            mEGLSlots이 생성한
                                                     [1]                                    EGL Image를 가리키게 한다.
                                                     [2]
                                                     [3]
                                                     [4]




                                                                                                           13
2.그래픽 버퍼 출력 요청
(2) postFramebuffer

Surfaceflinger.cpp
void SurfaceFlinger::postFramebuffer()
{
  hw.flip(mSwapRegion);
}

DisplayHardware.cpp
void DisplayHardware::flip(const Region& dirty) const
{
  mHwc->commit();

}

HWComposer.cpp(surfaceflingerdisplayhardware)
status_t HWComposer::commit() const {

     int err = mHwc->set(mHwc, mDpy, mSur, mList);
    mHwc는 HWC_HARDWARE_MODULE_ID 를 가지는 Module이다.
    return (status_t)err;
}

hwc.cpp(hardware/qcom/display/libhwcomposer)
static int hwc_set(…)
{
   eglSwapBuffers((EGLDisplay)dpy, (EGLSurface)sur);
}




                                                        14
참고자료


 안드로이드 미디어 프레임워크 –”개발자가 행복한 세상”

 Goolge Jelly bean Source




                                   15

Más contenido relacionado

La actualidad más candente

Startup JavaScript 6 - 함수, 스코프, 클로저
Startup JavaScript 6 - 함수, 스코프, 클로저Startup JavaScript 6 - 함수, 스코프, 클로저
Startup JavaScript 6 - 함수, 스코프, 클로저Circulus
 
Blockchain 4th dapp programming
Blockchain 4th dapp programmingBlockchain 4th dapp programming
Blockchain 4th dapp programmingihpark92
 
[스프링 스터디 2일차] 서비스 추상화
[스프링 스터디 2일차] 서비스 추상화[스프링 스터디 2일차] 서비스 추상화
[스프링 스터디 2일차] 서비스 추상화AnselmKim
 
Startup JavaScript 4 - 객체
Startup JavaScript 4 - 객체Startup JavaScript 4 - 객체
Startup JavaScript 4 - 객체Circulus
 
세션5. web3.js와 Node.js 를 사용한 dApp 개발
세션5. web3.js와 Node.js 를 사용한 dApp 개발세션5. web3.js와 Node.js 를 사용한 dApp 개발
세션5. web3.js와 Node.js 를 사용한 dApp 개발Jay JH Park
 
Blockchain 3rd smart contract programming
Blockchain 3rd smart contract programmingBlockchain 3rd smart contract programming
Blockchain 3rd smart contract programmingihpark92
 
객체 지향 발담그기 JCO 컨퍼런스 14회
객체 지향 발담그기 JCO 컨퍼런스 14회객체 지향 발담그기 JCO 컨퍼런스 14회
객체 지향 발담그기 JCO 컨퍼런스 14회beom kyun choi
 
세션4. 예제로 배우는 스마트 컨트랙트 프로그래밍
세션4. 예제로 배우는 스마트 컨트랙트 프로그래밍세션4. 예제로 배우는 스마트 컨트랙트 프로그래밍
세션4. 예제로 배우는 스마트 컨트랙트 프로그래밍Jay JH Park
 
세션3. geth 클라이언트 실습 및 모니터링과 시각화
세션3. geth 클라이언트 실습 및 모니터링과 시각화세션3. geth 클라이언트 실습 및 모니터링과 시각화
세션3. geth 클라이언트 실습 및 모니터링과 시각화Jay JH Park
 
세션1. block chain as a platform
세션1. block chain as a platform세션1. block chain as a platform
세션1. block chain as a platformJay JH Park
 
5-5. html5 connectivity
5-5. html5 connectivity5-5. html5 connectivity
5-5. html5 connectivityJinKyoungHeo
 
이더리움의 현황, 한계점 및 개선노력
이더리움의 현황, 한계점 및 개선노력 이더리움의 현황, 한계점 및 개선노력
이더리움의 현황, 한계점 및 개선노력 Younghoon Moon
 
NDC11_슈퍼클래스
NDC11_슈퍼클래스NDC11_슈퍼클래스
NDC11_슈퍼클래스noerror
 
GCGC- CGCII 서버 엔진에 적용된 기술 (1)
GCGC- CGCII 서버 엔진에 적용된 기술 (1)GCGC- CGCII 서버 엔진에 적용된 기술 (1)
GCGC- CGCII 서버 엔진에 적용된 기술 (1)상현 조
 
GCGC- CGCII 서버 엔진에 적용된 기술 (2) - Perfornance
GCGC- CGCII 서버 엔진에 적용된 기술 (2) - PerfornanceGCGC- CGCII 서버 엔진에 적용된 기술 (2) - Perfornance
GCGC- CGCII 서버 엔진에 적용된 기술 (2) - Perfornance상현 조
 
Blockchain 1st bitcoin_core
Blockchain 1st bitcoin_coreBlockchain 1st bitcoin_core
Blockchain 1st bitcoin_coreihpark92
 
07 스레드스케줄링,우선순위,그리고선호도
07 스레드스케줄링,우선순위,그리고선호도07 스레드스케줄링,우선순위,그리고선호도
07 스레드스케줄링,우선순위,그리고선호도ssuser3fb17c
 
GCGC- CGCII 서버 엔진에 적용된 기술 (4) - Executing System
GCGC- CGCII 서버 엔진에 적용된 기술 (4) - Executing SystemGCGC- CGCII 서버 엔진에 적용된 기술 (4) - Executing System
GCGC- CGCII 서버 엔진에 적용된 기술 (4) - Executing System상현 조
 
코어 이더리움
코어 이더리움 코어 이더리움
코어 이더리움 Jay JH Park
 

La actualidad más candente (20)

Startup JavaScript 6 - 함수, 스코프, 클로저
Startup JavaScript 6 - 함수, 스코프, 클로저Startup JavaScript 6 - 함수, 스코프, 클로저
Startup JavaScript 6 - 함수, 스코프, 클로저
 
Blockchain 4th dapp programming
Blockchain 4th dapp programmingBlockchain 4th dapp programming
Blockchain 4th dapp programming
 
[스프링 스터디 2일차] 서비스 추상화
[스프링 스터디 2일차] 서비스 추상화[스프링 스터디 2일차] 서비스 추상화
[스프링 스터디 2일차] 서비스 추상화
 
Startup JavaScript 4 - 객체
Startup JavaScript 4 - 객체Startup JavaScript 4 - 객체
Startup JavaScript 4 - 객체
 
세션5. web3.js와 Node.js 를 사용한 dApp 개발
세션5. web3.js와 Node.js 를 사용한 dApp 개발세션5. web3.js와 Node.js 를 사용한 dApp 개발
세션5. web3.js와 Node.js 를 사용한 dApp 개발
 
Blockchain 3rd smart contract programming
Blockchain 3rd smart contract programmingBlockchain 3rd smart contract programming
Blockchain 3rd smart contract programming
 
Clean code appendix 1
Clean code appendix 1Clean code appendix 1
Clean code appendix 1
 
객체 지향 발담그기 JCO 컨퍼런스 14회
객체 지향 발담그기 JCO 컨퍼런스 14회객체 지향 발담그기 JCO 컨퍼런스 14회
객체 지향 발담그기 JCO 컨퍼런스 14회
 
세션4. 예제로 배우는 스마트 컨트랙트 프로그래밍
세션4. 예제로 배우는 스마트 컨트랙트 프로그래밍세션4. 예제로 배우는 스마트 컨트랙트 프로그래밍
세션4. 예제로 배우는 스마트 컨트랙트 프로그래밍
 
세션3. geth 클라이언트 실습 및 모니터링과 시각화
세션3. geth 클라이언트 실습 및 모니터링과 시각화세션3. geth 클라이언트 실습 및 모니터링과 시각화
세션3. geth 클라이언트 실습 및 모니터링과 시각화
 
세션1. block chain as a platform
세션1. block chain as a platform세션1. block chain as a platform
세션1. block chain as a platform
 
5-5. html5 connectivity
5-5. html5 connectivity5-5. html5 connectivity
5-5. html5 connectivity
 
이더리움의 현황, 한계점 및 개선노력
이더리움의 현황, 한계점 및 개선노력 이더리움의 현황, 한계점 및 개선노력
이더리움의 현황, 한계점 및 개선노력
 
NDC11_슈퍼클래스
NDC11_슈퍼클래스NDC11_슈퍼클래스
NDC11_슈퍼클래스
 
GCGC- CGCII 서버 엔진에 적용된 기술 (1)
GCGC- CGCII 서버 엔진에 적용된 기술 (1)GCGC- CGCII 서버 엔진에 적용된 기술 (1)
GCGC- CGCII 서버 엔진에 적용된 기술 (1)
 
GCGC- CGCII 서버 엔진에 적용된 기술 (2) - Perfornance
GCGC- CGCII 서버 엔진에 적용된 기술 (2) - PerfornanceGCGC- CGCII 서버 엔진에 적용된 기술 (2) - Perfornance
GCGC- CGCII 서버 엔진에 적용된 기술 (2) - Perfornance
 
Blockchain 1st bitcoin_core
Blockchain 1st bitcoin_coreBlockchain 1st bitcoin_core
Blockchain 1st bitcoin_core
 
07 스레드스케줄링,우선순위,그리고선호도
07 스레드스케줄링,우선순위,그리고선호도07 스레드스케줄링,우선순위,그리고선호도
07 스레드스케줄링,우선순위,그리고선호도
 
GCGC- CGCII 서버 엔진에 적용된 기술 (4) - Executing System
GCGC- CGCII 서버 엔진에 적용된 기술 (4) - Executing SystemGCGC- CGCII 서버 엔진에 적용된 기술 (4) - Executing System
GCGC- CGCII 서버 엔진에 적용된 기술 (4) - Executing System
 
코어 이더리움
코어 이더리움 코어 이더리움
코어 이더리움
 

Destacado

Android audio system(audioflinger)
Android audio system(audioflinger)Android audio system(audioflinger)
Android audio system(audioflinger)fefe7270
 
Android audio system(오디오 출력-트랙생성)
Android audio system(오디오 출력-트랙생성)Android audio system(오디오 출력-트랙생성)
Android audio system(오디오 출력-트랙생성)fefe7270
 
Android audio system(audioplicy_service)
Android audio system(audioplicy_service)Android audio system(audioplicy_service)
Android audio system(audioplicy_service)fefe7270
 
Android audio system(audiopolicy_manager)
Android audio system(audiopolicy_manager)Android audio system(audiopolicy_manager)
Android audio system(audiopolicy_manager)fefe7270
 
Surface flingerservice(서피스플링거서비스초기화)
Surface flingerservice(서피스플링거서비스초기화)Surface flingerservice(서피스플링거서비스초기화)
Surface flingerservice(서피스플링거서비스초기화)fefe7270
 
Android media framework overview
Android media framework overviewAndroid media framework overview
Android media framework overviewJerrin George
 
Android audio system(audio_hardwareinterace)
Android audio system(audio_hardwareinterace)Android audio system(audio_hardwareinterace)
Android audio system(audio_hardwareinterace)fefe7270
 
Android audio system(오디오 출력-트랙활성화)
Android audio system(오디오 출력-트랙활성화)Android audio system(오디오 출력-트랙활성화)
Android audio system(오디오 출력-트랙활성화)fefe7270
 
Android Training (Media)
Android Training (Media)Android Training (Media)
Android Training (Media)Khaled Anaqwa
 
Android chromium web view
Android chromium web viewAndroid chromium web view
Android chromium web view朋 王
 
Camera camcorder framework overview(ginger bread)
Camera camcorder framework overview(ginger bread)Camera camcorder framework overview(ginger bread)
Camera camcorder framework overview(ginger bread)fefe7270
 
Chrome & Webkit overview
Chrome & Webkit overviewChrome & Webkit overview
Chrome & Webkit overviewBin Chen
 
2016-08-20 01 Дмитрий Рабецкий, Сергей Сорокин. Опыт работы с Android Medi...
2016-08-20 01 Дмитрий Рабецкий, Сергей Сорокин. Опыт работы с Android Medi...2016-08-20 01 Дмитрий Рабецкий, Сергей Сорокин. Опыт работы с Android Medi...
2016-08-20 01 Дмитрий Рабецкий, Сергей Сорокин. Опыт работы с Android Medi...Омские ИТ-субботники
 
안드로이드 MediaPlayer & VideoView
안드로이드 MediaPlayer & VideoView안드로이드 MediaPlayer & VideoView
안드로이드 MediaPlayer & VideoViewEunjoo Im
 
Stagefright recorder part1
Stagefright recorder part1Stagefright recorder part1
Stagefright recorder part1fefe7270
 
Android media codec 사용하기
Android media codec 사용하기Android media codec 사용하기
Android media codec 사용하기Taehwan kwon
 
Android Audio & OpenSL
Android Audio & OpenSLAndroid Audio & OpenSL
Android Audio & OpenSLYoss Cohen
 
Android's Multimedia Framework
Android's Multimedia FrameworkAndroid's Multimedia Framework
Android's Multimedia FrameworkOpersys inc.
 

Destacado (19)

Android audio system(audioflinger)
Android audio system(audioflinger)Android audio system(audioflinger)
Android audio system(audioflinger)
 
Android audio system(오디오 출력-트랙생성)
Android audio system(오디오 출력-트랙생성)Android audio system(오디오 출력-트랙생성)
Android audio system(오디오 출력-트랙생성)
 
Android audio system(audioplicy_service)
Android audio system(audioplicy_service)Android audio system(audioplicy_service)
Android audio system(audioplicy_service)
 
Android Audio System
Android Audio SystemAndroid Audio System
Android Audio System
 
Android audio system(audiopolicy_manager)
Android audio system(audiopolicy_manager)Android audio system(audiopolicy_manager)
Android audio system(audiopolicy_manager)
 
Surface flingerservice(서피스플링거서비스초기화)
Surface flingerservice(서피스플링거서비스초기화)Surface flingerservice(서피스플링거서비스초기화)
Surface flingerservice(서피스플링거서비스초기화)
 
Android media framework overview
Android media framework overviewAndroid media framework overview
Android media framework overview
 
Android audio system(audio_hardwareinterace)
Android audio system(audio_hardwareinterace)Android audio system(audio_hardwareinterace)
Android audio system(audio_hardwareinterace)
 
Android audio system(오디오 출력-트랙활성화)
Android audio system(오디오 출력-트랙활성화)Android audio system(오디오 출력-트랙활성화)
Android audio system(오디오 출력-트랙활성화)
 
Android Training (Media)
Android Training (Media)Android Training (Media)
Android Training (Media)
 
Android chromium web view
Android chromium web viewAndroid chromium web view
Android chromium web view
 
Camera camcorder framework overview(ginger bread)
Camera camcorder framework overview(ginger bread)Camera camcorder framework overview(ginger bread)
Camera camcorder framework overview(ginger bread)
 
Chrome & Webkit overview
Chrome & Webkit overviewChrome & Webkit overview
Chrome & Webkit overview
 
2016-08-20 01 Дмитрий Рабецкий, Сергей Сорокин. Опыт работы с Android Medi...
2016-08-20 01 Дмитрий Рабецкий, Сергей Сорокин. Опыт работы с Android Medi...2016-08-20 01 Дмитрий Рабецкий, Сергей Сорокин. Опыт работы с Android Medi...
2016-08-20 01 Дмитрий Рабецкий, Сергей Сорокин. Опыт работы с Android Medi...
 
안드로이드 MediaPlayer & VideoView
안드로이드 MediaPlayer & VideoView안드로이드 MediaPlayer & VideoView
안드로이드 MediaPlayer & VideoView
 
Stagefright recorder part1
Stagefright recorder part1Stagefright recorder part1
Stagefright recorder part1
 
Android media codec 사용하기
Android media codec 사용하기Android media codec 사용하기
Android media codec 사용하기
 
Android Audio & OpenSL
Android Audio & OpenSLAndroid Audio & OpenSL
Android Audio & OpenSL
 
Android's Multimedia Framework
Android's Multimedia FrameworkAndroid's Multimedia Framework
Android's Multimedia Framework
 

Similar a Surface flingerservice(서피스 출력 요청 jb)

Effective c++(chapter 5,6)
Effective c++(chapter 5,6)Effective c++(chapter 5,6)
Effective c++(chapter 5,6)문익 장
 
TCP echo 서버 및 클라이언트 예제 스터디
TCP echo 서버 및 클라이언트 예제 스터디TCP echo 서버 및 클라이언트 예제 스터디
TCP echo 서버 및 클라이언트 예제 스터디quxn6
 
Easy gameserver
Easy gameserverEasy gameserver
Easy gameserver진상 문
 
20140122 techdays mini 앱 개발 세미나(3) - 센서활용 앱 개발
20140122 techdays mini  앱 개발 세미나(3) - 센서활용 앱 개발20140122 techdays mini  앱 개발 세미나(3) - 센서활용 앱 개발
20140122 techdays mini 앱 개발 세미나(3) - 센서활용 앱 개발영욱 김
 
중급 소켓프로그래밍
중급 소켓프로그래밍중급 소켓프로그래밍
중급 소켓프로그래밍quxn6
 
Smart rover 통신 분석
Smart rover 통신 분석Smart rover 통신 분석
Smart rover 통신 분석Jang Suk Jung
 
TR 069 클라이언트 검토자료 3편
TR 069 클라이언트 검토자료 3편TR 069 클라이언트 검토자료 3편
TR 069 클라이언트 검토자료 3편ymtech
 
Tcp server / client
Tcp server / clientTcp server / client
Tcp server / client문익 장
 
[Swift] Command
[Swift] Command[Swift] Command
[Swift] CommandBill Kim
 
Hoons 닷넷 정기세미나
Hoons 닷넷 정기세미나Hoons 닷넷 정기세미나
Hoons 닷넷 정기세미나병걸 윤
 
Half sync/Half Async
Half sync/Half AsyncHalf sync/Half Async
Half sync/Half Asyncscor7910
 
Vue.js 기초 실습.pptx
Vue.js 기초 실습.pptxVue.js 기초 실습.pptx
Vue.js 기초 실습.pptxwonyong hwang
 
GCGC- CGCII 서버 엔진에 적용된 기술 (6) - CGCII Server Sample
GCGC- CGCII 서버 엔진에 적용된 기술 (6) - CGCII Server SampleGCGC- CGCII 서버 엔진에 적용된 기술 (6) - CGCII Server Sample
GCGC- CGCII 서버 엔진에 적용된 기술 (6) - CGCII Server Sample상현 조
 

Similar a Surface flingerservice(서피스 출력 요청 jb) (14)

Effective c++(chapter 5,6)
Effective c++(chapter 5,6)Effective c++(chapter 5,6)
Effective c++(chapter 5,6)
 
Nodejs_chapter3
Nodejs_chapter3Nodejs_chapter3
Nodejs_chapter3
 
TCP echo 서버 및 클라이언트 예제 스터디
TCP echo 서버 및 클라이언트 예제 스터디TCP echo 서버 및 클라이언트 예제 스터디
TCP echo 서버 및 클라이언트 예제 스터디
 
Easy gameserver
Easy gameserverEasy gameserver
Easy gameserver
 
20140122 techdays mini 앱 개발 세미나(3) - 센서활용 앱 개발
20140122 techdays mini  앱 개발 세미나(3) - 센서활용 앱 개발20140122 techdays mini  앱 개발 세미나(3) - 센서활용 앱 개발
20140122 techdays mini 앱 개발 세미나(3) - 센서활용 앱 개발
 
중급 소켓프로그래밍
중급 소켓프로그래밍중급 소켓프로그래밍
중급 소켓프로그래밍
 
Smart rover 통신 분석
Smart rover 통신 분석Smart rover 통신 분석
Smart rover 통신 분석
 
TR 069 클라이언트 검토자료 3편
TR 069 클라이언트 검토자료 3편TR 069 클라이언트 검토자료 3편
TR 069 클라이언트 검토자료 3편
 
Tcp server / client
Tcp server / clientTcp server / client
Tcp server / client
 
[Swift] Command
[Swift] Command[Swift] Command
[Swift] Command
 
Hoons 닷넷 정기세미나
Hoons 닷넷 정기세미나Hoons 닷넷 정기세미나
Hoons 닷넷 정기세미나
 
Half sync/Half Async
Half sync/Half AsyncHalf sync/Half Async
Half sync/Half Async
 
Vue.js 기초 실습.pptx
Vue.js 기초 실습.pptxVue.js 기초 실습.pptx
Vue.js 기초 실습.pptx
 
GCGC- CGCII 서버 엔진에 적용된 기술 (6) - CGCII Server Sample
GCGC- CGCII 서버 엔진에 적용된 기술 (6) - CGCII Server SampleGCGC- CGCII 서버 엔진에 적용된 기술 (6) - CGCII Server Sample
GCGC- CGCII 서버 엔진에 적용된 기술 (6) - CGCII Server Sample
 

Surface flingerservice(서피스 출력 요청 jb)

  • 2. 1.노말 서피스 출력(서비스 클라이언트) 그래픽 버퍼의 가상 주소를 획득한 후 그래픽 버퍼의 메모리에 랜더링 하여 서피스 플링거로 출력 요청하게 된다.  노말 서피스의 출력 요청 과정 SurfaceTextureClient의 queueBuffer함수는 서피스 플링거에게 출력할 버퍼를 알려준다. int SurfaceTextureClient::queueBuffer(android_native_buffer_t* buffer) { timestamp = systemTime(SYSTEM_TIME_MONOTONIC); 해당 버퍼의 마지막 출력 요청 시간. int i = getSlotFromBufferLocked(buffer); 출력 요청할 버퍼의 인덱스를 검색한다. ISurfaceTexture::QueueBufferOutput output; ISurfaceTexture::QueueBufferInput input(timestamp, crop, mScalingMode, mTransform); status_t err = mSurfaceTexture->queueBuffer(i, input, &output); BufferQueue의 queueBuffer를 호출한다. ( i : 출력할 버퍼 인덱스, input(timestamp:해당 버퍼의 출력 요청 시간등), output:서버에 저장된 그래픽 버퍼의 가로,세로 값을 저장함. 이 값은 애플리케이션에서 다음 그래픽 버퍼 획득 시 기본 값으로 사용 됨.) } 2
  • 3. 2.노말 서피스 출력(서비스 서버) 출력 방식은 동기, 비동기 2가지의 경우가 있다. 1.동기식:애플리케이션에서 출력 요청이 한번 발생하면 서피스 플링거 서비스에서도 한번의 출력이 발생 됨. 2.비동기식:출력 요청이 발생한 횟수에 관계없이 서피스 플링거 서비스의 합성에 맞추어 화면 출력이 됨. status_t BufferQueue::queueBuffer(int buf, const QueueBufferInput& input, QueueBufferOutput* output) { if (mSynchronousMode) {  동기식일 경우 mQueue.push_back(buf);  출력 대기 큐의 제일 마지막에 넣는다.(FIFO 방식) listener = mConsumerListener; mConsumerListener 는 SurfaceTexture 생성자에서 BufferQueue::ProxyConsumerListener 로 설정되어 있음. 이 lister는 출력 가능한 버퍼가 대기 하고 있다는 것을 서피스 플링거에게 알려줌. } else 비동기식 { if (mQueue.empty()) 출력 대기 큐에 대기하는 버퍼가 없다면 { mQueue.push_back(buf);  현재 요청된 버퍼를 대기 큐에 저장함. listener = mConsumerListener; } else {  출력 대기 하고 있는 버퍼가 있다면 Fifo::iterator front(mQueue.begin()); 출력 대기 큐의 첫번째 인덱스를 획득해서, mSlots[*front].mBufferState = BufferSlot::FREE; 슬롯의 상태를 FREE로 만든다. *front = buf;  출력 대기 큐의 첫번째 인덱스에 새롭게 요청한 인덱스를 넣는다. } mSlots[buf].mBufferState = BufferSlot::QUEUED;  버퍼의 상태를 QUEUED로 바꿈.  즉, 클라이언트는 출력 요청 하였고,서피스 플링거 서비스는 해당 버퍼를 아직 합성하지 않았다는 의미 임. mDequeueCondition.broadcast();  FREE상태를 기다리는 dequeueBuffer 함수를 깨운다. if (listener != 0) { listener->onFrameAvailable(); 서피스 플링거에게 합성 신호를 보내게 요청 함. } 3
  • 4. 2.노말 서피스 출력(서비스 서버) void BufferQueue::ProxyConsumerListener::onFrameAvailable() { sp<BufferQueue::ConsumerListener> listener(mConsumerListener.promote()); if (listener != NULL) { listener->onFrameAvailable(); } } SurfaceTexture는 BufferQueue::ConsumerListener 를 상속 받기 때문에 SurfaceTexture::onFrameAvailable가 호출 된다. SurfaceTexture.cpp void SurfaceTexture::onFrameAvailable() { if (listener != NULL) { ST_LOGV("actually calling onFrameAvailable"); listener->onFrameAvailable(); } } Layer.cpp struct FrameQueuedListener : public SurfaceTexture::FrameAvailableListener { FrameQueuedListener(Layer* layer) : mLayer(layer) { } virtual void onFrameAvailable() { if (that != 0) { that->onFrameQueued(); } }}; void Layer::onFrameQueued() { android_atomic_inc(&mQueuedFrames);  mQueuedFrames는 출력 요청이 발생한 횟수를 저장함. mFlinger->signalLayerUpdate(); 서피스 플링거에게 합성 시그널을 보냄. } 4
  • 5. 3.디스플레이 이벤트 동기화 젤리빈부터 하드웨어에서 발생하는 Vsync 이벤트에 맞춰 렌더링을 시작하도록 변경 됨. 서피스 플링거 역시 Vsync 에 맞춰 합성을 시작 함. Vsync Event 1.연속적 통지: Vsync 이벤트 발생 시 마다 이벤트 통지 2. 일회성 통지: Vsync 이벤트 요청 시 마다 이벤트 통지 서피스 플링거는 일회성 통지를 사용, 즉 출력 버퍼 큐에 새로운 버퍼가 추가되면 Vsync 에 맞춰 합성 시그널이 발생됨. SurfaceFlinger.cpp void SurfaceFlinger::signalLayerUpdate() { mEventQueue.invalidate(); } Messagequeue.cpp void MessageQueue::invalidate() { mEvents->requestNextVsync();  mEvents 는 EventThread 의 Connection class를 가르킨다. } EventThread.cpp void EventThread::Connection::requestNextVsync() { mEventThread->requestNextVsync(this);  mEventThread 는 EventThread를 가르킨다. } void EventThread::requestNextVsync( const sp<EventThread::Connection>& connection) { if (connection->count < 0) {  count의 초기 값이 -1이다. connection->count = 0;  count 값이 0 이면 일회성 통지를 의미함. mCondition.broadcast();  EventThread::threadLoop() 에서 기다리는 thread를 깨움. } } 5
  • 6. 3.디스플레이 이벤트 동기화  EventThread::threadLoop() 에서 Vsync가 발생 할때 까지 대기 하다 mCondition.broadcast(); 가 불리면 깨어 난다. bool EventThread::threadLoop() { do { do { timestamp = mVSyncTimestamp;  mVSyncTimestamp는 HWComposer로 부터 Vsync가 전달되면 갱신된다. 즉, HWComposer 로 부터 전달된 Vsync로 깨어난 경우가 아니라면, mVSyncTimestamp 은 0 이다. 현재 경우는, requestNextVsync 에 의해 깨어 났기 때문에 mVSyncTimestamp 가 0 이다. mVSyncTimestamp = 0; bool waitForNextVsync = false; size_t count = mDisplayEventConnections.size(); VSync 이벤트를 기다리는 수신자들(서피스 플링거)을 획득한다. for (size_t i=0 ; i<count ; i++) { sp<Connection> connection =mDisplayEventConnections.itemAt(i).promote(); connectionList.add(connection); if (connection!=0 && connection->count >= 0) {  EventThread::requestNextVsync 에서 count 값을 0으로 설정했다. 이 의미는 Vsync 를 받아 출력해야 할 Event가 있다는 의미이다. waitForNextVsync = true; Vsync가 필요하다는 의미로 waitForNextVsync 를 설정 한다. break; } if (timestamp) {  timestamp 가 0 보다 크다는 것은 HWComposer 로 부터 Vsync가 발생 되었다는 의미이다.  현재 경우는 Vsync가 전달되지 않았기 때문에 0 이다. if (!waitForNextVsync) { } else { 이 경우는 HWComposer 로 부터 Vsync가 발생된 경우임으로 첫번째 do while문을 빠져 나간다. break; } } 6
  • 7. 3.디스플레이 이벤트 동기화 else {  HWComposer 로 부터 Vsync 가 발생 되지 않을 경우 if (waitForNextVsync) {  Vsync가 필요 함으로 enableVSyncLocked();  HWCompser에게 Vsync 발생 요청 } mCondition.wait(mLock);  HWCompser로 부터 Vsync 가 발생되기를 기다림. } while(true); // 첫번째 do while문 const size_t count = mDisplayEventConnections.size();  이벤트 쓰레드에 등록된 Vsync 이벤트 수신자를 획득한다. for (size_t i=0 ; i<count ; i++) { const int32_t count = connection->count; if (count >= 1) { reportVsync = true;  수신자의 모드가 연속(count =1) 일 경우 reportVsync 를 수신 할 수 있다. } else if (count >= -1) { If (count == 0) { reportVsync = true; 수신자의 모드가 일회성(count =0) 일 경우 reportVsync 를 수신 할 수 있다. } if (reportVsync) { displayEventConnections.add(connection);  Vsync를 수신 받을 수신자를 displayEventConnections 에 추가한다. } } while (!displayEventConnections.size());  Vsync를 수신 받을 수신자가 있기 때문에 두번째 do while 문을 벗어난다. vsync.header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC; 수신자에게 보낼 이벤트 타입 설정 vsync.header.timestamp = timestamp;  Vsync 발생 시간 const size_t count = displayEventConnections.size();  Vsync를 수신 받을 수신자의 개수를 가져온다. for (size_t i=0 ; i<count ; i++) { status_t err = conn->postEvent(vsync);  각 수신자에게 Vsync를 보낸다. } 7
  • 8. 3.디스플레이 이벤트 동기화  Vsync 수신시의 처리 애플리케이션 측에서는 choreographer class를 이용하면 Vsync 이벤트를 수신 할 수 있다. 서피스 플링거는 네이티브 루퍼에서 Vsync event를 수신한다. 네이티브 루퍼는 Vsync가 수신되면 MessageQueue::setEventThread 의 MessageQueue::cb_eventReceiver 가 불려진다. MessageQueue.cpp void MessageQueue::setEventThread(const sp<EventThread>& eventThread) { mEventThread = eventThread; mEvents = eventThread->createEventConnection(); mEventTube = mEvents->getDataChannel(); mLooper->addFd(mEventTube->getFd(), 0, ALOOPER_EVENT_INPUT, MessageQueue::cb_eventReceiver, this); } int MessageQueue::cb_eventReceiver(int fd, int events, void* data) { MessageQueue* queue = reinterpret_cast<MessageQueue *>(data); return queue->eventReceiver(fd, events); } int MessageQueue::eventReceiver(int fd, int events) { while ((n = DisplayEventReceiver::getEvents(mEventTube, buffer, 8)) > 0) { for (int i=0 ; i<n ; i++) { if (buffer[i].header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) { mHandler->signalRefresh();  MessageQueue::Handler::signalRefresh 를 호출한다. break; } } } 8
  • 9. 3.디스플레이 이벤트 동기화 void MessageQueue::Handler::signalRefresh() { if ((android_atomic_or(eventMaskRefresh, &mEventMask) & eventMaskRefresh) == 0) { mQueue.mLooper->sendMessage(this, Message(MessageQueue::REFRESH)); 네이티브 루퍼에 MessageQueue::REFRESH 를 보낸다. } } void MessageQueue::Handler::handleMessage(const Message& message) { case REFRESH: android_atomic_and(~eventMaskRefresh, &mEventMask); mQueue.mFlinger->onMessageReceived(message.what); Surfaceflinger의 onMessageReceived 를 호출한다. break; } } 9
  • 10. 4.레이어 합성과 화면 출력 Surfaceflinger의 onMessageReceived 함수는 화면 출력 준비가 된 레이어들을 모아서 합성한 후 프레임 버퍼에 출력한다. void SurfaceFlinger::onMessageReceived(int32_t what) { switch (what) { case MessageQueue::INVALIDATE: case MessageQueue::REFRESH: { …. handlePageFlip(); 레이어에 할당된 그래픽 버퍼를 EGL Image로 만들어 텍스쳐로 사용할 수 있도록 만든다.---(1) handleRepaint();합성 hw.compositionComplete(); 합성이 완료 되었다는 것을 하드웨어에게 알려줌. postFramebuffer();  완료된 합성 이미지를 프레임 버퍼에 출력.------------(2) } (1) handlePageFlip void SurfaceFlinger::handlePageFlip() { const bool visibleRegions = lockPageFlip(currentLayers); } bool SurfaceFlinger::lockPageFlip(const LayerVector& currentLayers) { layer->lockPageFlip(recomputeVisibleRegions); } Layer.cpp void Layer::lockPageFlip(bool& recomputeVisibleRegions) { if (mSurfaceTexture->updateTexImage(&r) < NO_ERROR) { return; } 10
  • 11. 3.레이어 합성과 화면 출력 status_t SurfaceTexture::updateTexImage(BufferRejecter* rejecter) { err = mBufferQueue->acquireBuffer(&item);  출력 대기 큐의 첫번째 요소에 저장된 버퍼를 획득한다. BufferQueue.cpp status_t BufferQueue::acquireBuffer(BufferItem *buffer) { if (!mQueue.empty()) { Fifo::iterator front(mQueue.begin()); int buf = *front; 출력 대기 큐의 첫번째 인덱스를 가져온다. buffer->mGraphicBuffer = mSlots[buf].mGraphicBuffer; 그래픽 버퍼를 변수에 저장. buffer->mTimestamp = mSlots[buf].mTimestamp;  버퍼의 출력 요청 시간 저장. mSlots[buf].mBufferState = BufferSlot::ACQUIRED;  버퍼 상태를 ACQUIRED 로 바꾸어서, 다시 queuebuffer 할 수 없도록 함. mQueue.erase(front);  다음 버퍼를 위해 출력 대기 큐에서 삭제. } if (item.mGraphicBuffer != NULL) {  획득한 버퍼 인덱스의 GraphicBuffer 가 있으면 mEGLSlots[buf].mGraphicBuffer = 0;  기존 mEGLSlots 의 내용을 지운다. if (mEGLSlots[buf].mEglImage != EGL_NO_IMAGE_KHR) { eglDestroyImageKHR(dpy, mEGLSlots[buf].mEglImage); mEGLSlots[buf].mEglImage = EGL_NO_IMAGE_KHR; } mEGLSlots[buf].mGraphicBuffer = item.mGraphicBuffer;  GraphicBuffer 다시 지정. } image = createImage(dpy, mEGLSlots[buf].mGraphicBuffer);  EGL Image를 다시 만든다. mEGLSlots[buf].mEglImage = image;  만든 EGL Image를 mEGLSlots에 저장한다. 11
  • 12. 3.레이어 합성과 화면 출력 glEGLImageTargetTexture2DOES(mTexTarget, (GLeglImageOES)image); 바인딩된 텍스쳐에 대한 소스를 생성한 EGL Image로 지정 한다. (즉, 어떤 EGL Image를 사용할지 결정 함.) if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) { status_t status = mBufferQueue->releaseBuffer(mCurrentTexture, dpy,  이전 버퍼를 release한다. mEGLSlots[mCurrentTexture].mFence); } BufferQueue.cpp status_t BufferQueue::releaseBuffer(int buf, EGLDisplay display,EGLSyncKHR fence) { if (mSlots[buf].mBufferState == BufferSlot::ACQUIRED) { mSlots[buf].mBufferState = BufferSlot::FREE; status를 FREE 로 만들고 } mDequeueCondition.broadcast();  FREE 인 버퍼가 있음을 broadcast한다. } mCurrentTexture = buf;  현재 index를 mCurrentTexture 에 저장 한다. mCurrentTextureBuf = mEGLSlots[buf].mGraphicBuffer; } 12
  • 13. 3.화면 출력 시 Buffer status 변경 BufferQueue::releaseBuffe에 의해 7 mslot의 4번 status가 FREE로 변경됨. mSlot 출력 대기 큐에서 [0] 4번 인덱스를 mQueue의 첫번 째 요소의 삭제 mQueue 1 mSlot의 status를 FREE로 만든다. 4 [1] [0] 2->4 X [2] F D->F EGL Image [1] [3] 5 2 출력할 버퍼의 인덱스를 mQueue의 처음에 넣는다. A 그래픽 버퍼 출력할 그래픽 버퍼를 [2] [4] EGL Image로 만든다. D->A acquireBuffer에 의해 3 Status 를 ACQUIRED로 변경함 mEGLSlots [0] 6 mEGLSlots이 생성한 [1] EGL Image를 가리키게 한다. [2] [3] [4] 13
  • 14. 2.그래픽 버퍼 출력 요청 (2) postFramebuffer Surfaceflinger.cpp void SurfaceFlinger::postFramebuffer() { hw.flip(mSwapRegion); } DisplayHardware.cpp void DisplayHardware::flip(const Region& dirty) const { mHwc->commit(); } HWComposer.cpp(surfaceflingerdisplayhardware) status_t HWComposer::commit() const { int err = mHwc->set(mHwc, mDpy, mSur, mList); mHwc는 HWC_HARDWARE_MODULE_ID 를 가지는 Module이다. return (status_t)err; } hwc.cpp(hardware/qcom/display/libhwcomposer) static int hwc_set(…) { eglSwapBuffers((EGLDisplay)dpy, (EGLSurface)sur); } 14
  • 15. 참고자료  안드로이드 미디어 프레임워크 –”개발자가 행복한 세상”  Goolge Jelly bean Source 15