目录
基于Android4.4源码
SurfaceFlinger绘制测试Demo
在Android系统中SurfaceFlinger是窗口系统,Surface代表一个窗口。SurfaceFlinger采用C/S架构,需通过客户端与SurfaceFlinger通信,对窗口进行相关操作。使用SurfaceFlinger绘制图像,首先需要创建一个Surface对象,再对Surface对象进行操作即可。具体有以下步骤
- 创建Surface对象
- 调用surface->lock对象获取Buffer
- 将图像数据填充到Buffer
- 调用surface->unlockAndPost发送数据到缓存
//step1
sp<SurfaceControl> control = mSession->createSurface(String8("MyWindow"), width, height, PIXEL_FORMAT_RGB_565);
sp<Surface> s = control->getSurface();
//step2
ANativeWindow_Buffer outBuffer;
Rect dirtyRect(0, 0, 480, 320);
status_t err = surface->lock(&outBuffer, &dirtyRect);
//step3
SkBitmap bitmap;
ssize_t bpr = outBuffer.stride * bytesPerPixel(outBuffer.format);
bitmap.setConfig(convertPixelFormat(outBuffer.format), outBuffer.width, outBuffer.height, bpr);
SkCanvas* nativeCanvas = SkNEW_ARGS(SkCanvas, (bitmap));
//相关绘制图像代码
.....
//step4
surface->unlockAndPost();
SurfaceFlinger系统工作流程
1、客户端侧相关实现
1. 创建SurfaceControl
SurfaceControl由SurfaceComposerClient::createSurface方法生成,在其内部调用了Client::createSurface方法,获取到了IGraphicBufferProducer代理对象,该对象即BufferQueue
,handle是SurfaceFlinger层的Layer对象,并将这两个参数作为形参传递给了SurfaceControl的构造函数,生成了一个SurfaceControl对象。
sp<SurfaceControl> control = mSession->createSurface(String8("MyWindow"), width, height, PIXEL_FORMAT_RGB_565);
SurfaceComposerClient.cpp文件实现如下
//SurfaceComposerClient.cpp
sp<SurfaceControl> SurfaceComposerClient::createSurface(const String8& name, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags)
{
sp<SurfaceControl> sur;
if (mStatus == NO_ERROR) {
sp<IBinder> handle;
sp<IGraphicBufferProducer> gbp;
status_t err = mClient->createSurface(name, w, h, format, flags, &handle, &gbp);
ALOGE_IF(err, "SurfaceComposerClient::createSurface error %s", strerror(-err));
if (err == NO_ERROR) {
sur = new SurfaceControl(this, handle, gbp);
}
}
return sur;
}
2. 创建Surface对象
该对应由SurfaceControl::getSurface方法生成,将mGrahicBufferProducer对象(即BufferQueue)传递给Surface的构造函数,生成一个Surface对象。
sp<Surface> s = control->getSurface();
SurfaceControl.cpp实现如下
//SurfaceControl.cpp
sp<Surface> SurfaceControl::getSurface() const
{
Mutex::Autolock _l(mLock);
if (mSurfaceData == 0) {
// This surface is always consumed by SurfaceFlinger, so the
// producerControlledByApp value doesn't matter; using false.
mSurfaceData = new Surface(mGraphicBufferProducer, false);
}
return mSurfaceData;
}
2、服务端侧相关实现
1. 创建Layer对象
调用Client::createSurface方法会生成一个Layer对象。Client通过进程通信调用SurfaceFlinger::createLayer方法,根据类型创建何种类型Layer,最终new出来一个Layer对象。Layer内部会生成一个BufferQueue对象,并将BufferQueue的代理对象返回给客户端,客户端相关图像由BufferQueue传递给Layer,交给SurfaceFlinger进行相关合成送显。
Layer对象实现了SurfaceFlingerConsumer::FrameAvailableListener,并在创建BufferQueue时进行注册,当BufferQueue有数据时,会回调Layer的onFrameAvailable方法。
//Client.cpp
status_t Client::createSurface(const String8& name, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags, sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp)
{
result = flinger->createLayer(name, client, w, h, format, flags, handle, gbp);
}
//SurfaceFlinger.cpp
status_t SurfaceFlinger::createNormalLayer(const sp<Client>& client, const String8& name, uint32_t w, uint32_t h, uint32_t flags, PixelFormat& format, sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp, sp<Layer>* outLayer)
{
*outLayer = new Layer(this, client, name, w, h, flags);
status_t err = (*outLayer)->setBuffers(w, h, format, flags);
if (err == NO_ERROR) {
*handle = (*outLayer)->getHandle();
//BufferQueue
*gbp = (*outLayer)->getBufferQueue();
}
return err;
}
Layer创建BufferQueue对象,并将自己注册到BufferQueue,当BufferQueue有数据时可及时响应。
//Layer.cpp
void Layer::onFirstRef() {
// Creates a custom BufferQueue for SurfaceFlingerConsumer to use
mBufferQueue = new SurfaceTextureLayer(mFlinger);
mSurfaceFlingerConsumer = new SurfaceFlingerConsumer(mBufferQueue, mTextureName);
mSurfaceFlingerConsumer->setConsumerUsageBits(getEffectiveUsage(0));
//注册有数据时回调
mSurfaceFlingerConsumer->setFrameAvailableListener(this);
mSurfaceFlingerConsumer->setName(mName);
}
2. 数据合成
Layer的onFrameAvailable方法会给SurfaceFlinger发消息,最终SurfaceFlinger会调用handleMessageRefresh方法进行Layer合成送显等操作。
//SurfaceFlinger.cpp
void SurfaceFlinger::handleMessageRefresh() {
ATRACE_CALL();
preComposition();
rebuildLayerStacks();
setUpHWComposer();
doDebugFlashRegions();
doComposition();
postComposition();
}
void SurfaceFlinger::preComposition()
{
bool needExtraInvalidate = false;
const LayerVector& layers(mDrawingState.layersSortedByZ);
const size_t count = layers.size();
for (size_t i=0 ; i<count ; i++) {
if (layers[i]->onPreComposition()) {
needExtraInvalidate = true;
}
}
if (needExtraInvalidate) {
signalLayerUpdate();
}
}
void SurfaceFlinger::setUpHWComposer() {
HWComposer& hwc(getHwComposer());
if (hwc.initCheck() == NO_ERROR) {
// set the per-frame data
for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
sp<const DisplayDevice> hw(mDisplays[dpy]);
for (size_t i=0 ; cur!=end && i<count ; ++i, ++cur) {
/*
* update the per-frame h/w composer data for each layer
* and build the transparent region of the FB
*/
const sp<Layer>& layer(currentLayers[i]);
//将Layer的数据传递给DisplayService
layer->setPerFrameData(hw, *cur);
}
}
}
status_t err = hwc.prepare();
ALOGE_IF(err, "HWComposer::prepare failed (%s)", strerror(-err));
for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
sp<const DisplayDevice> hw(mDisplays[dpy]);
hw->prepareFrame(hwc);
}
}
}
void SurfaceFlinger::doComposeSurfaces(const sp<const DisplayDevice>& hw, const Region& dirty)
{
// we're using h/w composer
for (size_t i=0 ; i<count && cur!=end ; ++i, ++cur) {
const sp<Layer>& layer(layers[i]);
const Region clip(dirty.intersect(tr.transform(layer->visibleRegion)));
if (!clip.isEmpty()) {
switch (cur->getCompositionType()) {
case HWC_FRAMEBUFFER: {
//调用Layer::draw方法进行绘制
layer->draw(hw, clip);
break;
}
}
}
layer->setAcquireFence(hw, *cur);
}
}
void SurfaceFlinger::postComposition()
{
const LayerVector& layers(mDrawingState.layersSortedByZ);
const size_t count = layers.size();
for (size_t i=0 ; i<count ; i++) {
layers[i]->onPostComposition();
}
}
最终会调用Layer的onDraw方法,使用DisplayDevice进行绘制。
SurfaceFlingerConsumer继承GLConsumer内部持有Layer的BufferQueue,即给上层Surface使用的BufferQueue。
//Layer.cpp
void Layer::onDraw(const sp<const DisplayDevice>& hw, const Region& clip) const
{
// Bind the current buffer to the GL texture, and wait for it to be
// ready for us to draw into.
status_t err = mSurfaceFlingerConsumer->bindTextureImage();
RenderEngine& engine(mFlinger->getRenderEngine());
drawWithOpenGL(hw, clip);
engine.disableTexturing();
}
//SurfaceFlingerConsumer.cpp
status_t SurfaceFlingerConsumer::bindTextureImage()
{
Mutex::Autolock lock(mMutex);
return bindTextureImageLocked();
}
//Consumer.cpp
status_t GLConsumer::bindTextureImageLocked() {
EGLImageKHR image = mEglSlots[mCurrentTexture].mEglImage;
glEGLImageTargetTexture2DOES(mTexTarget, (GLeglImageOES)image);
}
status_t GLConsumer::updateAndReleaseLocked(const BufferQueue::BufferItem& item)
{
int buf = item.mBuf;
// If the mEglSlot entry is empty, create an EGLImage for the gralloc
// buffer currently in the slot in ConsumerBase.
//
// We may have to do this even when item.mGraphicBuffer == NULL (which
// means the buffer was previously acquired), if we destroyed the
// EGLImage when detaching from a context but the buffer has not been
// re-allocated.
if (mEglSlots[buf].mEglImage == EGL_NO_IMAGE_KHR) {
EGLImageKHR image = createImage(mEglDisplay, mSlots[buf].mGraphicBuffer, item.mCrop);
mEglSlots[buf].mEglImage = image;
mEglSlots[buf].mCropRect = item.mCrop;
}
// Do whatever sync ops we need to do before releasing the old slot.
err = syncForReleaseLocked(mEglDisplay);
// Update the GLConsumer state.
mCurrentTexture = buf;
mCurrentTextureBuf = mSlots[buf].mGraphicBuffer;
mCurrentCrop = item.mCrop;
mCurrentTransform = item.mTransform;
mCurrentScalingMode = item.mScalingMode;
mCurrentTimestamp = item.mTimestamp;
mCurrentFence = item.mFence;
mCurrentFrameNumber = item.mFrameNumber;
}
Region Layer::latchBuffer(bool& recomputeVisibleRegions)
{
status_t updateResult = mSurfaceFlingerConsumer->updateTexImage(&r);
}
status_t SurfaceFlingerConsumer::updateTexImage(BufferRejecter* rejecter)
{
BufferQueue::BufferItem item;
// Acquire the next buffer.
// In asynchronous mode the list is guaranteed to be one buffer
// deep, while in synchronous mode we use the oldest buffer.
err = acquireBufferLocked(&item, computeExpectedPresent());
// Release the previous buffer.
err = updateAndReleaseLocked(item);
}
status_t GLConsumer::updateAndReleaseLocked(const BufferQueue::BufferItem& item)
{
status_t err = NO_ERROR;
int buf = item.mBuf;
// If the mEglSlot entry is empty, create an EGLImage for the gralloc
// buffer currently in the slot in ConsumerBase.
//
// We may have to do this even when item.mGraphicBuffer == NULL (which
// means the buffer was previously acquired), if we destroyed the
// EGLImage when detaching from a context but the buffer has not been
// re-allocated.
if (mEglSlots[buf].mEglImage == EGL_NO_IMAGE_KHR) {
EGLImageKHR image = createImage(mEglDisplay, mSlots[buf].mGraphicBuffer, item.mCrop);
mEglSlots[buf].mEglImage = image;
mEglSlots[buf].mCropRect = item.mCrop;
}