Surface flingerservice(서피스 상태 변경 jb)

3,626 views

Published on

0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
3,626
On SlideShare
0
From Embeds
0
Number of Embeds
237
Actions
Shares
0
Downloads
0
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Surface flingerservice(서피스 상태 변경 jb)

  1. 1. SurfaceFlingerService(서피스 상태 변경-JB ) 박철희 1
  2. 2. 1.서피스 상태 변경 요청(서비스 클라이언트)1.서피스 추가/삭제2.개별 레이어 상태 변경(크기,zorder)3.프레임 상태 변경(orientation변경)1.서피스 추가/삭제 서피스가 추가 또는 삭제 되면 전역 레이어 목록이 변경되어야 한다. 이를 위해서 추가 또는 삭제 시에 mTransactionFlags 에 eTransactionNeeded을 설정하고 Vsync를 발생 시킨다.sp<ISurface> SurfaceFlinger::createSurface(…){ normalLayer = createNormalSurface(client, d, w, h, flags, format); setTransactionFlags(eTransactionNeeded); uint32_t SurfaceFlinger::setTransactionFlags(uint32_t flags) {} uint32_t old = android_atomic_or(flags, &mTransactionFlags); if ((old & flags)==0) { // wake the server upstatus_t SurfaceFlinger::removeSurface() signalTransaction();{ } … return old; setTransactionFlags(eTransactionNeeded); }} void SurfaceFlinger::signalTransaction() { mEventQueue.invalidate(); MessageQueue에서 Vsync 발생 시킴. } 2
  3. 3. 1.서피스 상태 변경 요청(서비스 클라이언트)2.개별 레이어 상태 변경(크기,zorder) -레이어(서피스) 상태 변경은 트랜잭션 시작과 종료 사이에만 가능하다. -다수의 상태 변경 함수를 동시에 중첩하여 설정 할 수 있다. ex)fade out 의 기능과 같이 메뉴가 투명해 지면서 축소가 되고 위치가 변경이 되는 경우 “투명,축소,위치변경”이 동시에 실행 된다.  레이어의 상태를 변경할 때 클라이언트와 서버의 동작 3
  4. 4. 1.서피스 상태 변경 요청(서비스 클라이언트)Bootanimation.cppstatus_t BootAnimation::readyToRun(){ sp<SurfaceControl> control = session()->createSurface(getpid(), 0, dinfo.w, dinfo.h, PIXEL_FORMAT_RGBA_8888); SurfaceComposerClient::openGlobalTransaction(); transaction 시작 control->setLayer(0x40000000); 서피스의 zorder 변경 SurfaceComposerClient::closeGlobalTransaction(); transaction 종료}1)Transaction 시작status_t SurfaceComposerClient:: openGlobalTransaction(){  ICS 이후 부터 특별한 동작은 하지 않음.}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
  5. 5. 1.서피스 상태 변경 요청(서비스 클라이언트)SurfaceComposerClient.cppstatus_t SurfaceComposerClient::setLayer(SurfaceID id, int32_t z){ return getComposer().setLayer(this, id, z);}status_t Composer::setLayer(const sp<SurfaceComposerClient>& client, SurfaceID id, int32_t z) { layer_state_t* s = getLayerStateLocked(client, id); 서피스의 상태 변경 정보를 저장할 layer_state_t를 생성한다. s->what |= ISurfaceComposer::eLayerChanged; s->z = z; layer state 구조체에 what(상태 변경 이벤트),z(zoder값)을 저장한다. return NO_ERROR;}layer_state_t* Composer::getLayerStateLocked(const sp<SurfaceComposerClient>& client, SurfaceID id) { ComposerState s; s.client = client->mClient; 서피스 클라이언트 리코트 서비스에 대한 Proxy(ISurfaceComposerClient)를 저장한다. s.state.surface = id; 상태가 변경된 서피스의 지역 식별자를 저장한다. ssize_t index = mStates.indexOf(s); if (index < 0) { // we dont have it, add an initialized layer_state to our list index = mStates.add(s);  상태가 변경된 layer_state_t 구조체를 mStates 에 넣는다. 이 mStates 는 서피스 플링거에게 전달되어 서피스 상태 변경에 사용된다. } ComposerState* const out = mStates.editArray(); return &(out[index].state);} 5
  6. 6. 1.서피스 상태 변경 요청(서비스 클라이언트)3. transaction 종료SurfaceComposerClient.cppstatic void closeGlobalTransaction(bool synchronous){ Composer::getInstance().closeGlobalTransactionImpl(synchronous);}void Composer::closeGlobalTransactionImpl(bool synchronous){ sp<ISurfaceComposer> sm(getComposerService()); Vector<ComposerState> transaction; transaction = mStates; 애플리케이션에서 발생한 상태 변경 이벤트를 mStates 변수에 발생한 순서대로 저장해 두고, 서피스 플링거에게 전달 한다. mStates.clear(); mStates 배열을 초기화 한다. orientation = mOrientation; mOrientation = ISurfaceComposer::eOrientationUnchanged; sm->setTransactionState(transaction, orientation, flags); 서비스 플링거에게 서피스들의 상태 변경 정보를 저장한 transaction 과 출력 방향을 저장한 orientation을 전달 한다.} 6
  7. 7. 2.서피스 상태 변경 (서비스 서버)서피스 플링거 서비스는 레이어의 상태 변경이 발생하면 상태 변경 이벤트의 종류에 따라 처리한다. 상태 변경 동작 값이 설정되는 경우 이벤트 eTransactionNeeded 전역 레이어 목록에 1) setOrientation: 회전 방향 변경 포함된 2) Freeze: 디스플레이가 갱신되지 않도록 만듦. 모든 레이어의 무효화 3) Unfreeze:freeze상태를 해지 영역을 재계산 4) createSurface:레이어 생성 5) destroySurface:레이어 삭제 6) setLayer:레이어의 높이 값 변경 eTraversalNeeded 상태가 변경된 레이어 1) setPosition:위치 결정 의 무효화 영역을 재계 2) setLayer:레이어의 높이 값 변경 산 3) setSize: 크기 번경 4) setAlpha: 개별 레이어 전체의 투명도 변경 5) setMatrix: 레이어 메트릭스 변경 6) setTransparentRegionHint: 레이어 반투명 영역 변경 7) segFlags:레이어 가시성 변경(hide,show) 7
  8. 8. 2.서피스 상태 변경 (서비스 서버)void SurfaceFlinger::setTransactionState(const Vector<ComposerState>& state, int orientation, uint32_t flags){ if (mCurrentState.orientation != orientation) {  이전 설정된 출력 방향과 다르면 mCurrentState.orientation = orientation; 현재 출력 방향을 설정하고 transactionFlags |= eTransactionNeeded; 전체 레이어의 무효화 영역을 설정하기 위해 eTransactionNeeded 설정함. } const size_t count = state.size(); for (size_t i=0 ; i<count ; i++) { const ComposerState& s(state[i]); sp<Client> client( static_cast<Client *>(s.client.get()) ); 변경 요청이 발생한 서피스 클라이언트를 획득한다. transactionFlags |= setClientStateLocked(client, s.state); } if (transactionFlags) { setTransactionFlags(transactionFlags);  변경된 플래그 값을 mTransactionFlags 에 반영하고 signalTransaction 를 호출해서 합성 이벤트를 발생시킨다.(mEventQueue.invalidate()) if (flags & eSynchronous) { mTransationPending = true;  모든 레이어의 가로,세로 값이 변경 될때 까지 기다리기 위한 변수 } while (mTransationPending) { status_t err = mTransactionCV.waitRelative(mStateLock, s2ns(5)); 레이어의 크기가 재설정 될 동안 기다린다. mTransationPending = false; break; }} 8
  9. 9. 2.서피스 상태 변경 (서비스 서버)uint32_t SurfaceFlinger::setClientStateLocked(const sp<Client>& client, const layer_state_t& s){ if (what & eLayerChanged) { ssize_t idx = mCurrentState.layersSortedByZ.indexOf(layer); if (layer->setLayer(s.z)) { mCurrentState.layersSortedByZ.removeAt(idx); 전역 레이어 목록에서 해당 레이어 삭제 mCurrentState.layersSortedByZ.add(layer); 다시 추가. flags |= eTransactionNeeded|eTraversalNeeded; zorder 변경은 개별 레이어의 상태 변경 (eTraversalNeeded) 및 전역 레이어 목록 변경(eTransactionNeeded) 이 필요함. } if (what & eVisibilityChanged) { if (layer->setFlags(s.flags, s.mask)) flags |= eTraversalNeeded; 가시성 변경은 “개별 레이어 상태 변경”에 해당함으로 서피스 플링거의 mTransactionFlags 변수에 eTraversalNeeded 값 설정. }}Layerbase.cppbool LayerBase::setFlags(uint8_t flags, uint8_t mask) { const uint32_t newFlags = (mCurrentState.flags & ~mask) | (flags & mask); Layerbase의 mCurrentState. 변수에 변경할 속성을 set한다. mCurrentState.sequence++; 서피스의 상태가 변경되었다는 사실을 mCurrentState.의 sequence를 하나 증가 시켜 표시. mCurrentState.flags = newFlags; return true;} 9
  10. 10. 3.윈도우 속성 변경(서비스 클라이언트) 서피스 텍스쳐에 설정된 안드로이드 네이티브 윈도우의 속성값을 변경. 윈도우 속성 변경 예 ex)setBufferCount() native_window_set_usage 그래픽 버퍼의 속성을 설정 native_window_set_crop 최종적으로 디스플레이에 출력 될 화면의 크기를 결정 함. native_window_set_buffer_count 그래픽 버퍼의 개수 지정 native_window_set_buffers_transform 윈도우의 출력 방향 결정 native_window_set_buffers_timestamp 윈도우의 화면 출력을 요청하면 서버에서는 출력 요청이 발생한 시간 값을 저장 native_window_api_connect 윈도우의 사용을 위해 윈도우와 어플리케이션을 연결함. 10
  11. 11. 3.윈도우 속성 변경(서비스 클라이언트)Ex)Cameraservice의 setPreviewWindowstatus_t CameraService::Client::setPreviewWindow(const sp<IBinder>& binder, const sp<ANativeWindow>& window){ if (window != 0) { result = native_window_api_connect(window.get(), NATIVE_WINDOW_API_CAMERA);}Window.hstatic inline int native_window_api_connect(struct ANativeWindow* window, int api){ return window->perform(window, NATIVE_WINDOW_API_CONNECT, api);}Surfacetextureclient.cppint SurfaceTextureClient::perform(int operation, va_list args){ case NATIVE_WINDOW_API_CONNECT: res = dispatchConnect(args); break;}int SurfaceTextureClient::dispatchConnect(va_list args) { int api = va_arg(args, int); return connect(api);}int SurfaceTextureClient::connect(int api){ int err = mSurfaceTexture->connect(api, &output); output.deflate(&mDefaultWidth, &mDefaultHeight, &mTransformHint, &numPendingBuffers);} 11
  12. 12. 3.윈도우 속성 변경(서비스 서버)BufferQueue.cppstatus_t BufferQueue::connect(int api, QueueBufferOutput* output){ switch (api) { case NATIVE_WINDOW_API_EGL: case NATIVE_WINDOW_API_CPU: case NATIVE_WINDOW_API_MEDIA: case NATIVE_WINDOW_API_CAMERA: mConnectedApi = api; output->inflate(mDefaultWidth, mDefaultHeight, mTransformHint,mQueue.size()); 인자로 넘어온 output에 mDefaultWidth, mDefaultHeight 값 들을 넣는다. 이 값들은 SurfaceTextureclient의 connect함수에서 deflate로 다시 값들을 가져 간다. } break; default: err = -EINVAL; break; } mBufferHasBeenQueued = false; return err;} 12
  13. 13. 4.그래픽 버퍼 요청(서비스 클라이언트) 그래픽 버퍼 획득 과정 13
  14. 14. 4.그래픽 버퍼 요청(서비스 클라이언트)Ex)그래픽 버퍼 요청OmxCodec.cppstatus_t OMXCodec::pushBlankBuffersToNativeWindow(){ … for (int i = 0; i < numBufs + 1; i++) { err = mNativeWindow->dequeueBuffer(mNativeWindow.get(), &anb); -----(1) sp<GraphicBuffer> buf(new GraphicBuffer(anb, false)); -----(2) err = buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img)); -----(3) *img = 0; 가상 주소의 내용을 0으로 채운다(blank buffer) err = buf->unlock();  그래픽 버퍼의 사용완료를 그래픽 HAL에게 알림. err = mNativeWindow->queueBuffer(mNativeWindow.get(),buf->getNativeBuffer()); 수정된 그래픽 버퍼를 출력 요청 한다.}1) mNativeWindow->dequeueBuffer(mNativeWindow.get(), &anb);dequeueBuffe 는 ANativeWindow 를 상속 받은 SurfaceTextureClient 의 hook_dequeubuufer에 매핑되어 있다.int SurfaceTextureClient::hook_dequeueBuffer(ANativeWindow* window, ANativeWindowBuffer** buffer) { SurfaceTextureClient* c = getSelf(window); return c->dequeueBuffer(buffer);  c는 SurfaceTextureClient 를 가리 킴.}int SurfaceTextureClient::dequeueBuffer(android_native_buffer_t** buffer) {status_t result = mSurfaceTexture->dequeueBuffer(&buf, reqW, reqH, mReqFormat, mReqUsage); -----(1-1)sp<GraphicBuffer>& gbuf(mSlots[buf].buffer); if ((result & ISurfaceTexture::BUFFER_NEEDS_REALLOCATION) || gbuf == 0) { result = mSurfaceTexture->requestBuffer(buf, &gbuf);} -----(1-2) *buffer = gbuf.get(); return OK;} 14
  15. 15. 4.그래픽 버퍼 요청(서비스 클라이언트)(1-1) mSurfaceTexture->dequeueBuffer(&buf, reqW, reqH, mReqFormat, mReqUsage);- mSurfaceTexture 는 ISurfaceTexture를 가리킨다. 이를 통해 BufferQueue의 dequeueBuffer를 호출한다.- Buf:호출 시 그래픽 버퍼의 번호를 저장할 정수형 변수, 이 정수형 변수를 사용할 그래픽 버퍼의 index를 가리킨다.- reqW, reqH: 생성할 그래픽 버퍼의 가로,세로 크기  그래픽 버퍼 요청 시 클라이언트와 서버의 상호 동작 15
  16. 16. 4.그래픽 버퍼 요청(서비스 클라이언트)(1) 애플리케이션은 ISurfaceTexture 서비스 프록시의 dequeueBuffer()를 호출하여 그래픽 버펴를 요청한다.(2) 서버 측에서는 BufferSlot 배열에서 FREE 상태의 슬롯을 찾는다. 그런 후 해당 배열의 상태를 DEQUEUED로 변경한다.(3) Bufferslot 배열의 인덱스를 반환한다. 배열의 인덱스의 그래픽 버퍼가 없어면 requestbuffer로 할당된 그래픽 버퍼를 요청한다(4) 애플리케이션이 렌더링이 완료된 그래픽 버퍼를 queuebuffer()를 이용하여 서버측에 전달한다.(5) 서퍼에서는 버퍼 큐(mQueue)에 해당 그래픽 버퍼의 인덱스를 넣는다. 그런 후 해당 배열의 상태를 QUEUED로 변경한다.(1-2) mSurfaceTexture->requestBuffer(buf, &gbuf); if ((result & ISurfaceTexture::BUFFER_NEEDS_REALLOCATION) || gbuf == 0) { 해당 그래픽 버퍼 번호에 처음으로 그래픽 번호를 요청하거나, 요청한 버퍼의 크기나 픽셀 포맷 등이 기존에 할당된 버퍼와 다른 경우 서버측에게 새로 할당 된 그래픽 버퍼의 전달을 요청한다. (이 경우 dequeueBuffer함수는 BUFFER_NEEDS_REALLOCATION를 반환 함.) result = mSurfaceTexture->requestBuffer(buf, &gbuf); *buffer = gbuf.get(); 생성된 그래픽 버퍼를 애플리케이션으로 반환 함. return OK;}ISurfaceTexture.cppvirtual status_t requestBuffer(int bufferIdx, sp<GraphicBuffer>* buf) { Parcel data, reply; data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor()); data.writeInt32(bufferIdx); 요청할 버퍼의 index status_t result =remote()->transact(REQUEST_BUFFER, data, &reply); 서버에 REQUEST_BUFFER 요청 보냄. 서버는 해당하는 인덱스의 BufferSlot 배열에 GraphicBuffer 객체를 생성한다. bool nonNull = reply.readInt32(); if (nonNull) { *buf = new GraphicBuffer(); 서피스 텍스쳐 클라이언트에도 GraphicBuffer를 생성한다. reply.read(**buf); 서버영역에서 생성된 그래픽 버퍼의 정보를 방금 생성한 GraphicBuffer 에 채워 넣는다. 이렇게 함으로써 서버에서 생성된 그래픽 버퍼와 동일한 값을 클라이언트에서도 유지하게 된다. } result = reply.readInt32(); return result; } 16
  17. 17. 4.그래픽 버퍼 요청(서비스 클라이언트)(2) sp<GraphicBuffer> buf(new GraphicBuffer(anb, false)); GraphicBuffer::GraphicBuffer( ANativeWindowBuffer(anb)를 가지는 GraphicBuffer를 생성한다. ANativeWindowBuffer* buffer, bool keepOwnership) {(3) err = buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img)); width = buffer->width; 애플리케이션에서 버퍼의 사용을 위해서는 접근 가능한 그래픽 버퍼의 가상주소를 height = buffer->height; 필요로 한다. stride = buffer->stride; 그래픽 버퍼의 가상주소를 획득하기 위해 GraphicBuffer class의 lock함수가 format = buffer->format; 불려진다. usage = buffer->usage; handle = buffer->handle;status_t GraphicBuffer::lock(uint32_t usage, void** vaddr) }{ const Rect lockBounds(width, height); status_t res = lock(usage, lockBounds, vaddr); //vaddr: 가상주소를 저장할 포인터 return res;}status_t GraphicBuffer::lock(uint32_t usage, const Rect& rect, void** vaddr){ status_t res = getBufferMapper().lock(handle, usage, rect, vaddr);  getBufferMapper 함수를 이용하여 전달된 그래픽 버퍼에 대한 가상 주소를 반환한다. return res;} 17
  18. 18. 4.그래픽 버퍼 생성(서비스 서버)서비스 서버 측에서 그래픽 버퍼를 할당하는 과정은1)버퍼 슬롯의 개수 확인 2)버퍼 슬롯의 인덱스 획득 3)그래픽 버퍼 할당 으로 구분된다.1)버퍼 슬롯의 개수 확인status_t BufferQueue::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h, uint32_t format, uint32_t usage){ while (tryAgain) { const int minBufferCountNeeded = mSynchronousMode ? mMinSyncBufferSlots : mMinAsyncBufferSlots; 동기식, 비동기식에 따라 필요한 최소 버퍼수를 minBufferCountNeeded 에 넣는다. const bool numberOfBuffersNeedsToChange = !mClientBufferCount && ((mServerBufferCount != mBufferCount) || (mServerBufferCount < minBufferCountNeeded));  setBufferCount 함수로 버퍼 개수를 설정하거나(mClientBufferCount 변경), 서버에서 설정한 버퍼의 수가 BufferQueue에 설정된 버퍼의 수와 다르거나 (mServerBufferCount != mBufferCount), 서버에서 설정한 버퍼의 수가 설정 가능한 최소 버퍼 수보다 작을 경우 (mServerBufferCount < minBufferCountNeeded numberOfBuffersNeedsToChange를 true로 setting한다. 이 의미는 버퍼의 수를 수정하겠다는 의미 이다. if (!mQueue.isEmpty() && numberOfBuffersNeedsToChange) {  버퍼의 수 변경이 필요하지만, 출력 대기 큐(mQueue)에 출력 요청한 인덱스가 남아 있다면, mDequeueCondition.wait(mMutex); 출력 대기 큐가 모두 소비 될 때 까지 기다린다. continue; } if (numberOfBuffersNeedsToChange) { freeAllBuffersLocked();  mSlot의 모든 배열을 초기화 한다.(mSlot에 할당된 모든 그래픽 버퍼가 해지 된다.) mBufferCount = mServerBufferCount; 서버에서 요청한 버퍼 수를 mBufferCount 에 저장한다. if (mBufferCount < minBufferCountNeeded) mBufferCount = minBufferCountNeeded; 버퍼 최소값보다 작으면 버퍼 최소 값으로 저장 한다. returnFlags |= ISurfaceTexture::RELEASE_ALL_BUFFERS; SurfaceTextureClient의 dequeueBuffer함수는 서버에서 RELEASE_ALL_BUFFERS 가 반환되면 freeAllBuffers를 불러 클라이언트에 매핑된 그래픽 버퍼를 모두 해지 한다.} 18
  19. 19. 4.그래픽 버퍼 생성(서비스 서버)2)사용 가능한 버퍼 슬롯의 인덱스 획득status_t BufferQueue::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h, uint32_t format, uint32_t usage){ while (tryAgain) { … found = INVALID_BUFFER_SLOT; foundSync = INVALID_BUFFER_SLOT; for (int i = 0; i < mBufferCount; i++) { const int state = mSlots[i].mBufferState; if (state == BufferSlot::FREE) 버퍼의 상태가 free인 값을 검색하여 인덱스를 획득한다. { foundSync = i; found = i; } tryAgain = found == INVALID_BUFFER_SLOT; if (tryAgain) { mDequeueCondition.wait(mMutex); 사용 가능한 버퍼가 없는 경우, FREE인 상태의 버퍼가 생길 때 까지 기다린다. } *outBuf = found; dequeueBuffer() 함수 호출 시 전달 된 인자에 검색에 성공한 BufferSlot 배열의 인덱스를 저장하여, 클라이언트 측으로 전달한다. … 19
  20. 20. 4.그래픽 버퍼 생성(서비스 서버)3)그래픽 버퍼 할당status_t BufferQueue::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h, uint32_t format, uint32_t usage){ while (tryAgain) { … const sp<GraphicBuffer>& buffer(mSlots[buf].mGraphicBuffer); 검색된 인덱스의 GraphicBuffer 객체의 참조를 획득한다. 이전에 할당된 그래픽 버퍼가 있다면 재사용이 가능한다. mSlots[buf].mBufferState = BufferSlot::DEQUEUED; 검색한 슬롯의 상태를 DEQUEUED 로 변경한다. if ((buffer == NULL) || needNewBuffer(currentGeometry, requiredGeometry, updatedGeometry) || ((uint32_t(buffer->usage) & usage) != usage)) 그래픽 버퍼를 새로 생성해야 하면(처음 생성 or size 변경) { sp<GraphicBuffer> graphicBuffer( mGraphicBufferAlloc->createGraphicBuffer( w, h, format, usage, &error)); 그래픽 버퍼를 생성한다. mGraphicBufferAlloc은 IGraphicBufferAlloc 서비스 프락시를 가리킨다. mSlots[buf].mGraphicBuffer = graphicBuffer; 생성한 그래픽 버퍼를 해당 슬롯의 mGraphicBuffer 에 저장한다. returnFlags |= ISurfaceTexture::BUFFER_NEEDS_REALLOCATION; 새롭게 할당된 버퍼가 있을 경우 설정하는 value이다. 클라이언트 측에서는 BUFFER_NEEDS_REALLOCATION 이 전달되면 ISurfaceTexture의 requestBuffer() 함수를 호출하여 생성된 그래픽 버퍼를 전달 받는다.}SurfaceFlinger.cppsp<GraphicBuffer> GraphicBufferAlloc::createGraphicBuffer(uint32_t w, uint32_t h, PixelFormat format, uint32_t usage, status_t* error) { sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(w, h, format, usage, mBufferSize)); status_t err = graphicBuffer->initCheck(); return graphicBuffer;} 20
  21. 21. 4.그래픽 버퍼 생성(서비스 서버)GraphicBuffer.cppGraphicBuffer::GraphicBuffer(uint32_t w, uint32_t h, PixelFormat reqFormat, uint32_t reqUsage, uint32_t bufferSize) : BASE(), mOwner(ownData), mBufferMapper(GraphicBufferMapper::get()), mInitCheck(NO_ERROR), mIndex(-1){ mInitCheck = initSize(w, h, reqFormat, reqUsage, bufferSize);} mOwner: 그래픽 버퍼의 메모리에 대한 소유자 -ownNone: 애플리케이션 영역에서 그래픽 버퍼가 생성될 때 할당 됨. 하지만 requestBuffer() 함수를 호출하여 그래픽 버퍼를 전달 받을 때 이 값은 ownHandle 로 변경 됨. -ownHandle: 클라이언트에서 사용할 그래픽 버퍼의 경우. -ownData: 서버에서 사용할 그래픽 버퍼의 경우 mBufferMapper: 그래픽 버퍼의 메모리 할당 후 애플리케이션에서 매핑 할 때 사용하는 GraphicBufferMapper 클래스 객체 저장.status_t GraphicBuffer::initSize(uint32_t w, uint32_t h, PixelFormat format, uint32_t reqUsage){ GraphicBufferAllocator& allocator = GraphicBufferAllocator::get(); status_t err = allocator.alloc(w, h, format, reqUsage, &handle, &stride);  GraphicBufferAllocator 클래스의 alloc함수를 호출함. return err; GraphicBufferAllocator::} GraphicBufferAllocator(): mAllocDev(0) {status_t GraphicBufferAllocator::alloc(…) hw_get_module({ GRALLOC_HARDWARE_MODULE_ID, err = mAllocDev->alloc(mAllocDev, w, h, format, usage, handle, stride); &module); 그래픽 할당 HAL의 alloc 함수를 호출 한다. if (err == 0) {} gralloc_open(module, &mAllocDev); } } 21
  22. 22. 4.그래픽 버퍼 생성(서비스 서버)dequeueBuffer 의 result가 BUFFER_NEEDS_REALLOCATION 일경우 mSurfaceTexture->requestBuffer를 호출하여BufferQueue 의 requestBuffer를 부른다.ISurfaceTexture.cppstatus_t BnSurfaceTexture::onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags){ switch(code) { case REQUEST_BUFFER: { CHECK_INTERFACE(ISurfaceTexture, data, reply); int bufferIdx = data.readInt32(); sp<GraphicBuffer> buffer; int result = requestBuffer(bufferIdx, &buffer); reply->writeInt32(buffer != 0); if (buffer != 0) { reply->write(*buffer); 반환된 그래픽 버퍼를 바인더에 쓴다.  이렇게 함으로써 서피스 플링거 영역에 생성된 그래픽 버퍼와 같은 값을 가진 GraphicBuffer 객체를 어플리케이션 영역에 생성 할 수 있게 된다. } reply->writeInt32(result); return NO_ERROR; } break;}BufferQueue.cppstatus_t BufferQueue::requestBuffer(int slot, sp<GraphicBuffer>* buf) { *buf = mSlots[slot].mGraphicBuffer; 클라이언트로 부터 전달받은 인덱스에 해당하는 그래픽 버퍼를 GraphicBuffer 에 저장하여 반환한다. return NO_ERROR;} 22
  23. 23. 참고.그래픽 버퍼 요청 /생성 과정 Application SurfaceTextureClient BufferQueue 1 2 SurfaceTextureClient BufferQueue에 요청 버퍼 요청 에 요청 버퍼 요청 (dequeubuffer) (dequeubuffer) 0 mSlot[0] 0 mSlot[0] D 9 4 전달 받은 1 mSlot[1] 찾은 FREE Slost의 1 mSlot[1] D GraphicBuffer를 Index를 return함. 사용하기 위해 2 mSlot[2] 2 mSlot[2] F 가상주소를 Mapping 후 … … 그래픽 버퍼를 사용한다. 5 Requestbuffer를 호출해서 할당된 그래픽 버퍼를 전달 받음 Requestbuffer를 3 Status가 FREE인 slot 6 호출시 클라이언트 측에 을 찾고 그래픽 버퍼 빈 GraphicBuffer 를 생성 할당 함. GraphicBuffer GraphicBuffer GraphicBuffer 8 7 그래픽 버퍼 그래픽 버퍼 그래픽 버퍼 클라이언트 측의 서버에서 생성된 GraphicBuffer를 동일한 그래픽 버퍼를 Application에서 사용하기 클라이언트 측의 GraphicBuffer 위해서 전달 한다. 로 읽어 옴. 23
  24. 24. 참고자료 안드로이드 미디어 프레임워크 –”개발자가 행복한 세상” Goolge Jelly bean Source 24

×