• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
Surface flingerservice(서피스 상태 변경 및 출력 요청)
 

Surface flingerservice(서피스 상태 변경 및 출력 요청)

on

  • 1,372 views

 

Statistics

Views

Total Views
1,372
Views on SlideShare
1,252
Embed Views
120

Actions

Likes
0
Downloads
0
Comments
0

3 Embeds 120

http://fefe7270.blogspot.kr 109
http://fefe7270.blogspot.com 10
http://fefe7270.blogspot.in 1

Accessibility

Categories

Upload Details

Uploaded via as Microsoft PowerPoint

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    Surface flingerservice(서피스 상태 변경 및 출력 요청) Surface flingerservice(서피스 상태 변경 및 출력 요청) Presentation Transcript

    • SurfaceFlingerService(서피스 상태 변경 및 출력 요청) 박철희 1
    • 화면 출력 요청 전 과정 2
    • 1.서피스 상태 변경 -서피스 추가/삭제1.서피스 추가/삭제2.개별 레이어 상태 변경(크기,zorder)3.프레임 상태 변경(orientation변경)1.서피스 추가/삭제 서피스가 추가 또는 삭제 되면 전역 레이어 목록이 변경되어야 한다. 이를 위해서 추가 또는 삭제 시에 mTransactionFlags 에 eTransactionNeeded을 설정하고 surfaceflinger의 threadloop으로 signal을 보낸다.sp<ISurface> SurfaceFlinger::createSurface(…){ layer = createPushBuffersSurface(client, d, w, h, flags); setTransactionFlags(eTransactionNeeded);} uint32_t SurfaceFlinger::setTransactionFlags(uint32_t flags)status_t SurfaceFlinger::removeSurface() {{ uint32_t old = android_atomic_or(flags, &mTransactionFlags); … if ((old & flags)==0) { // wake the server up setTransactionFlags(eTransactionNeeded); signalEvent();} } return old; } 3
    • 1.서피스 상태 변경 종류-개별 레이어 상태 변경2.개별 레이어 상태 변경(크기,zorder) -레이어(서피스) 상태 변경은 트랜잭션 시작과 종료 사이에만 가능하다. -다수의 상태 변경 함수를 동시에 중첩하여 설정 할 수 있다. ex)fade out 의 기능과 같이 메뉴가 투명해 지면서 축소가 되고 위치가 변경이 되는 경우 “투명,축소,위치변경”이 동시에 실행 된다.Bootanimation.cppstatus_t BootAnimation::readyToRun(){ sp<SurfaceControl> control = session()->createSurface(getpid(), 0, dinfo.w, dinfo.h, PIXEL_FORMAT_RGBA_8888); session()->openTransaction();  transaction 시작 control->setLayer(0x40000000); 서피스의 zorder 변경 session()->closeTransaction();  transaction 종료}1)Transaction 시작status_t SurfaceComposerClient::openTransaction(){ mTransactionOpen++; open된 transaction을 나타내는 mTransactionOpen을 1 증가 시킴.}2) 서피스의 zorder 변경Surface.cppstatus_t SurfaceControl::setLayer(int32_t layer){ status_t err = validate(); if (err < 0) return err; const sp<SurfaceComposerClient>& client(mClient); return client->setLayer(mToken, layer);  상태 변경의 대상이 되는 레이어를 알려 주기 위해 mToken을 넘겨 준다.} (mToken은 SurfaceControl 생성자에서 생성된 layer를 가리키게 된다.) 4
    • 1.서피스 상태 변경 종류- 개별 레이어 상태 변경SurfaceComposerClient.cppstatus_t SurfaceComposerClient::setLayer(SurfaceID id, int32_t z){ layer_state_t* s = lockLayerState(id); dummy layer state 구조체를 생성하고 return 받는다. s->what |= ISurfaceComposer::eLayerChanged; s->z = z; dummy layer state 구조체에 what(상태 변경 이벤트),z(zoder값)을 저장한다. unlockLayerState(); return NO_ERROR;}layer_state_t* SurfaceComposerClient::lockLayerState(SurfaceID id){ s = get_state_l(id); if (!s) mLock.unlock(); return s;}layer_state_t* SurfaceComposerClient::get_state_l(SurfaceID index){ layer_state_t& dummy(*mPrebuiltLayerState);  mPrebuiltLayerState는 onFirstRef에서 만들어진 dummy layer state 구조체 dummy.surface = index; dummy state 구조체에 상태 변경 대상의 layer의 index를 대입 ssize_t i = mStates.indexOf(dummy); if (i < 0) { // we dont have it, add an initialized layer_state to our list i = mStates.add(dummy); mStates 에 dummy 구조체 추가. 이 mStates의 정보는 SurfaceFlinger쪽으로 전달 됨. } return mStates.editArray() + i;  추가된 dummy 구조체를 return} 5
    • 1.서피스 상태 변경 종류- 개별 레이어 상태 변경3. transaction 종료SurfaceComposerClient.cppstatus_t SurfaceComposerClient::closeTransaction(){ if (mTransactionOpen >= 2) {  transcation이 2개 이상일 경우에는 서피스 플링거에게 상태 변경을 요청하지 않고, mTransactionOpen만 1 감소 시키고 return 시킴(빈번한 transaction 처리를 방지하기 위해) mTransactionOpen--; return NO_ERROR; } mTransactionOpen = 0; const ssize_t count = mStates.size(); if (count) { mClient->setState(count, mStates.array()); mStates 에 추가된 dummy layer 구조체를 인자로 서피스 클라이언트의 setState함수를 호출 함. mStates.clear(); } return NO_ERROR;}status_t Client::setState(int32_t count, const layer_state_t* states){ return mFlinger->setClientState(this, count, states);} 6
    • 1.서피스 상태 변경 종류- 개별 레이어 상태 변경status_t SurfaceFlinger::setClientState(const sp<Client>& client, int32_t count,const layer_state_t* states){ if (what & eLayerChanged) { ssize_t idx = mCurrentState.layersSortedByZ.indexOf(layer); if (layer->setLayer(s.z)) { mCurrentState.layersSortedByZ.removeAt(idx); mCurrentState.layersSortedByZ.add(layer); // we need traversal (state changed) AND transaction (list changed) flags |= eTransactionNeeded|eTraversalNeeded; zorder 변경은 개별 레이어의 상태 변경 (eTraversalNeeded) 및 전역 레이어 목록 변경(eTransactionNeeded) 이 필요함. } if (flags) { setTransactionFlags(flags); surfaceflinger의 threadloop으로 signal을 보내서 상태 변경 처리를 한다. } 7
    • 1.서피스 상태 변경 종류-프레임 상태 변경3.프레임 상태 변경(orientation변경) -전역 레이어 목록에 있는 모든 레이어를 회전 각도에 맞게 재 계산해야 함.int SurfaceComposerClient::setOrientation(DisplayID dpy, int orientation, uint32_t flags){ sp<ISurfaceComposer> sm(getComposerService()); return sm->setOrientation(dpy, orientation, flags);}int SurfaceFlinger::setOrientation(DisplayID dpy, int orientation, uint32_t flags){ if (mCurrentState.orientation != orientation) {  현재 상태 값과 다를 때에만 재 계산 함. mCurrentState.orientation = orientation; mCurrentState와 mDrawingState의 orientation을 비교 setTransactionFlags(eTransactionNeeded);  전역 레이어 목록 변경 mTransactionCV.wait(mStateLock);  다른 레이어가 변경할 때 까지 기다림. }}Surfaceflinger의 threadloop에서 transaction을 처리하기 위한 handleTransactionLocked에서 commitTransaction를 호출 함.void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags){ commitTransaction();}void SurfaceFlinger::commitTransaction(){ mTransactionCV.broadcast();  setOrientation에서 기다리고 있는 conditionlock에게 signal 보냄.} 8
    • 2.그래픽 버퍼 출력 요청Ex)Cameraservice의 preview 출력void CameraService::Client::handlePreviewData(const sp<IMemory>& mem){ ssize_t offset; size_t size; sp<IMemoryHeap> heap = mem->getMemory(&offset, &size); if (!mUseOverlay) { if (mSurface != 0) { mSurface->postBuffer(offset); } }}void LayerBuffer::postBuffer(ssize_t offset){ source->postBuffer(offset);}void LayerBuffer::BufferSource::postBuffer(ssize_t offset){ buffers = mBufferHeap; sp<Buffer> buffer; if (buffers.heap != 0) { buffer = new LayerBuffer::Buffer(buffers, offset, mBufferSize); 1.offset에 해당하는 메모리 영역을 copybit을 이용할 수 있는 Nativebuffer에 저장 setBuffer(buffer);2.BufferSource객체의 mBuffer에 생성된 buffer class를 저장한다. mLayer.invalidate(); 3.서피스 플링거에게 출력 요청 함. } 9
    • 2.그래픽 버퍼 출력 요청1.offset에 해당하는 메모리 영역을 copybit을 이용할 수 있는 Nativebuffer에 저장buffer = new LayerBuffer::Buffer(buffers, offset, mBufferSize);LayerBuffer::Buffer::Buffer(const ISurface::BufferHeap& buffers, ssize_t offset, size_t bufferSize) struct NativeBuffer { : mBufferHeap(buffers), mCurrOffset(offset) copybit_image_t img;{ copybit_rect_t crop; int hor_stride; NativeBuffer& src(mNativeBuffer); int ver_stride;  mNativeBuffer에 offset에 해당하는 메모리 영역을 저장함. }; src.img.base = (void*)(intptr_t(buffers.heap->base()) + offset); src.img.handle = 0;2.BufferSource객체의 mBuffer에 생성된 buffer를 저장한다void LayerBuffer::BufferSource::setBuffer(const sp<LayerBuffer::Buffer>& buffer){ Mutex::Autolock _l(mBufferSourceLock); mBuffer = buffer;}Cf.copybit :그래픽 공유 메모리의 내용을 EGL_Image(Nativebuffer)로 고속으로 복사하기 위해 사용하는 hardware graphic module. 10
    • 2.그래픽 버퍼 출력 요청 surfaceflinger layerbuffer buffersource mBufferHeap mSource mBuffer buffer mNativeBuffer mBufferHeap 그래픽 공유 메모리 NativeBuffer 11
    • 2.그래픽 버퍼 출력 요청3.서피스 플링거에게 출력 요청 함.void LayerBase::invalidate(){ mFlinger->signalEvent();} Surfaceflinger의 threadloop void SurfaceFlinger::waitForEvent() { sp<MessageBase> msg = mEventQueue.waitMessage(timeout); switch (msg->what) { case MessageQueue::INVALIDATE: // invalidate message, just return to the main loop return; } } void SurfaceFlinger::handleRepaint() { layer->draw(clip); } Layerbase의 draw함수를 호출한다. (각 layer의 텍스처 or EGL Image를 생성하고 프레임 버퍼에 이미지를 그려 넣는다.) 12
    • 2.그래픽 버퍼 출력 요청Layerbase.cppvoid LayerBase::draw(const Region& clip) const{ onDraw(clip);}LayerBuffer.cppvoid LayerBuffer::BufferSource::onDraw(const Region& clip) const{ sp<Buffer> ourBuffer(getBuffer());  postbuffer()에서 생성한 Buffer 인스턴스를 가져온다. NativeBuffer src(ourBuffer->getBuffer());  Buffer class의 copybit 이미지로 사용 가능한 Nativebuffer type의 mNativeBuffer를 가져온다. copybit_device_t* copybit = mLayer.mBlitEngine;copybit module을 가져온다. err = initTempBuffer(); EGL Image를 생성하고 생성된 image를 NativeBuffer type인 mTempBuffer에 저장한다. const NativeBuffer& dst(mTempBuffer); err = copybit->stretch(copybit, &dst.img, &src.img,&dst.crop, &src.crop, &clip); copybit을 이용하여 src(그래픽 공유 메모리)의 내용을 EGL Image를 가리키고 있는 dst로 copy한다. mLayer.drawWithOpenGL(tempClip, mTexture); 생성된 EGL Image와 클립 정보(EGL image의 출력 영역)를 이용하여 각 레이어가 자신의 출력 영역에 그린다.} status_t LayerBuffer::BufferSource::initTempBuffer() const{ sp<GraphicBuffer> buffer = new GraphicBuffer( w, h, HAL_PIXEL_FORMAT_RGB_565, GraphicBuffer::USAGE_HW_TEXTURE | GraphicBuffer::USAGE_HW_2D | GRALLOC_USAGE_PRIVATE_1); EGL image를 위한 buffer 생성 13
    • 2.그래픽 버퍼 출력 요청 NativeBuffer& dst(mTempBuffer); dst.img.handle = (native_handle_t *)buffer->handle; NativeBuffer type인 dst에 GraphicBuffer로 생성된 buffer의 handle을 저장한다. dst.crop.l = 0; dst.crop.t = 0; dst.crop.r = w; dst.crop.b = h; crop에 출력 범위를 지정한다. err = mTextureManager.initEglImage(&mTexture, dpy, buffer); 생성된 buffer를 EGL Image의 버퍼로 지정한다. } surfaceflinger EGL layerbuffer buffersource NativeBuffer mBufferHeap Graphic mSource mBuffer Buffer buffer mNativeBuffer EGL Image mBufferHeap dst mTempBuffer 그래픽 공유 메모리 NativeBuffer Src Copybit을 이용한 고속복사 14