Everything begins when an activity draws to a surface
2D applications can use
1) drawing functions in Canvas to write to a Bitmap:android.graphics.Canvas.drawRect(), drawText(), etc
2) descendants of the View class to draw objects such as buttons and lists
3) a custom View class to implement your own appearance and behaviour
In all cases the drawing is rendered to a Surface which contains a GraphicBuffer
一个activity等Client画一个UI的流程如下:
ISurfaceComposer is the interface to talk to SurfaceFlinger, there’re two ways to get ISurfaceComposer interface in Client:
sp<ISurfaceComposer> composer;
composer = ComposerService::getComposerService();
or
getService("SurfaceFlinger", &composer);
ISurfaceComposerClient is the interface to create Surface. To get ISurfaceComposerClient interface, use the ISurfaceComposer instance returned above:
sp<ISurfaceComposerClient> composerClient = composer->createConnection();
The above two methods can be combined in single step:
sp<SurfaceComposerClient> composerClient = new SurfaceComposerClient;
To operate on Surface, you have to get SurfaceControl first, simply call createSurface on the SurfaceComposerClient instance:
sp<SurfaceControl> surfaceControl = composerClient->createSurface();
And call getSurface on SurfaceControl instance, you can finally get Surface:
sp<Surface> surface = surfaceControl->getSurface();
if (!mConnectedToCpu) {
int err = Surface::connect(NATIVE_WINDOW_API_CPU);
if (err) {
return err;
}
// we're intending to do software rendering from this point
setUsage(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN);
}
ANativeWindowBuffer* out;
int fenceFd = -1;
status_t err = dequeueBuffer(&out, &fenceFd);
ALOGE_IF(err, "dequeueBuffer failed (%s)", strerror(-err));
if (err == NO_ERROR) {
sp<GraphicBuffer> backBuffer(GraphicBuffer::getSelf(out));
const Rect bounds(backBuffer->width, backBuffer->height);
Region newDirtyRegion;
if (inOutDirtyBounds) {
newDirtyRegion.set(static_cast<Rect const&>(*inOutDirtyBounds));
newDirtyRegion.andSelf(bounds);
} else {
newDirtyRegion.set(bounds);
}
// figure out if we can copy the frontbuffer back
const sp<GraphicBuffer>& frontBuffer(mPostedBuffer);
const bool canCopyBack = (frontBuffer != 0 &&
backBuffer->width == frontBuffer->width &&
backBuffer->height == frontBuffer->height &&
backBuffer->format == frontBuffer->format);
if (canCopyBack) {
// copy the area that is invalid and not repainted this round
const Region copyback(mDirtyRegion.subtract(newDirtyRegion));
if (!copyback.isEmpty())
copyBlt(backBuffer, frontBuffer, copyback);
} else {
// if we can't copy-back anything, modify the user's dirty
// region to make sure they redraw the whole buffer
newDirtyRegion.set(bounds);
mDirtyRegion.clear();
Mutex::Autolock lock(mMutex);
for (size_t i=0 ; i<NUM_BUFFER_SLOTS ; i++) {
mSlots[i].dirtyRegion.clear();
}
}
{ // scope for the lock
Mutex::Autolock lock(mMutex);
int backBufferSlot(getSlotFromBufferLocked(backBuffer.get()));
if (backBufferSlot >= 0) {
Region& dirtyRegion(mSlots[backBufferSlot].dirtyRegion);
mDirtyRegion.subtract(dirtyRegion);
dirtyRegion = newDirtyRegion;
}
}
mDirtyRegion.orSelf(newDirtyRegion);
if (inOutDirtyBounds) {
*inOutDirtyBounds = newDirtyRegion.getBounds();
}
Surface::lock()函数中outBuffer就是backBuffer,是通过GraphicBufferProducer从BufferQueue中获取的空闲buffer。
获取了这个空闲的backBuffer之后就可以往backBuffer中填充数据,并通过queueBuffer发给SurfaceFlinger了(backBuffer是画画用的,frontBuffer是composite用的)。
所以Surface和SurfaceFlinger之间也是一个C/S架构,其桥梁就是BufferQueue。Surface从BufferQueue中获取空闲Buffer填充数据并发给BufferQueue。SurfaceFlinger也是从BufferQueue中获取buffer并画上去。buffer是共享缓冲区,所以会涉及互斥锁,buffer状态也有很多种,一般buffer会大致经过FREE->DEQUEUED->QUEUED->ACQUIRED->FREE这几种流程(状态机参考下面的BufferQueue state diagram)。如下图: