我是靠谱客的博主 阔达洋葱,最近开发中收集的这篇文章主要介绍SurfaceFlinger的渲染客户端Surface初始化,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

关于SurfaceFlinger他大部分都是三层架构

SurfaceFlinger是针对整个系统,

用户类本地binder服务端binder
ComposerServiceBpSurfaceComposerSurfaceFlinger
SurfaceComposerClientBpSurfaceComposerClientClient
SurfaceSurfaceControlIBinderLayer

这里数据结构三层,是方便管理,一个系统只有一个SurfaceFlinger。

每个应用拥有 一个SurfaceComposerClient,

每个窗体或者surface对应一个layer。

前两个业务逻辑相对简单,主要维护数据。而Surface,是比较复杂的,主要通过layer生成共享内存的管理类。然后交给程序端渲染。

高版本的android主要通过生产消费者模式。对于客户程序其实是一个生产者(Producer)。而服务端则是一个消费端(交个hw层渲染)。

下面我们主要分析一下surface以及layer的具体实现类。

Layer真实类型为BufferQueueLayer

我们从SurfaceComposerClientcreat出Surface这个过程追踪一下代码。了解一下过程。

2.1 用户端请求

这个过程相对简单,开始是通过调用SurfaceComposerClient的函数

sp<SurfaceControl> control = session()->createSurface(String8("uitest"),
resolution.getWidth(), resolution.getHeight(), PIXEL_FORMAT_RGB_565);
sp<SurfaceControl> SurfaceComposerClient::createSurface(const String8& name, uint32_t w, uint32_t h,
PixelFormat format, uint32_t flags,
SurfaceControl* parent,
LayerMetadata metadata,
uint32_t* outTransformHint) {
sp<SurfaceControl> s;
createSurfaceChecked(name, w, h, format, &s, flags, parent, std::move(metadata),
outTransformHint);
return s;
}
status_t SurfaceComposerClient::createSurfaceChecked(const String8& name, uint32_t w, uint32_t h,
PixelFormat format,
sp<SurfaceControl>* outSurface, uint32_t flags,
SurfaceControl* parent, LayerMetadata metadata,
uint32_t* outTransformHint) {
sp<SurfaceControl> sur;
status_t err = mStatus;
if (mStatus == NO_ERROR) {
sp<IBinder> handle;
sp<IBinder> parentHandle;
sp<IGraphicBufferProducer> gbp;
if (parent != nullptr) {
parentHandle = parent->getHandle();
}
uint32_t transformHint = 0;
err = mClient->createSurface(name, w, h, format, flags, parentHandle, std::move(metadata),
&handle, &gbp, &transformHint);
if (outTransformHint) {
*outTransformHint = transformHint;
}
ALOGE_IF(err, "SurfaceComposerClient::createSurface error %s", strerror(-err));
if (err == NO_ERROR) {
*outSurface = new SurfaceControl(this, handle, gbp, transformHint);
}
}
return err;
}

这里其实相对加单,就是调用client的createSurface,因为client类型是BpSurfaceComposerClient,其实这里客户端已经完成了任务,已经通过binder把请求发送给服务端的Client中了。下面我们进入第二阶段的代码阅读。他主要是服务端构造Layer,生成共享buffer,实现卡进程的数据(帧数据)共享

2.2 服务端处理

处理端其实到了Client.cpp的函数,其实相对比较简单,直接交给SurfaceFlinger处理:

status_t Client::createSurface(const String8& name, uint32_t w, uint32_t h, PixelFormat format,
uint32_t flags, const sp<IBinder>& parentHandle,
LayerMetadata metadata, sp<IBinder>* handle,
sp<IGraphicBufferProducer>* gbp, uint32_t* outTransformHint) {
// We rely on createLayer to check permissions.
return mFlinger->createLayer(name, this, w, h, format, flags, std::move(metadata), handle, gbp,
parentHandle, nullptr, outTransformHint);
}

具体代码如下:

status_t SurfaceFlinger::createLayer(const String8& name, const sp<Client>& client, uint32_t w,
uint32_t h, PixelFormat format, uint32_t flags,
LayerMetadata metadata, sp<IBinder>* handle,
sp<IGraphicBufferProducer>* gbp,
const sp<IBinder>& parentHandle, const sp<Layer>& parentLayer,
uint32_t* outTransformHint) {
sp<Layer> layer;
switch (flags & ISurfaceComposerClient::eFXSurfaceMask) {
case ISurfaceComposerClient::eFXSurfaceBufferQueue:
result = createBufferQueueLayer(client, std::move(uniqueName), w, h, flags,
std::move(metadata), format, handle, gbp, &layer);
break;
case ISurfaceComposerClient::eFXSurfaceBufferState:
result = createBufferStateLayer(client, std::move(uniqueName), w, h, flags,
std::move(metadata), handle, &layer);
break;
case ISurfaceComposerClient::eFXSurfaceEffect:
// check if buffer size is set for color layer.
if (w > 0 || h > 0) {
ALOGE("createLayer() failed, w or h cannot be set for color layer (w=%d, h=%d)",
int(w), int(h));
return BAD_VALUE;
}
result = createEffectLayer(client, std::move(uniqueName), w, h, flags,
std::move(metadata), handle, &layer);
break;
case ISurfaceComposerClient::eFXSurfaceContainer:
// check if buffer size is set for container layer.
if (w > 0 || h > 0) {
ALOGE("createLayer() failed, w or h cannot be set for container layer (w=%d, h=%d)",
int(w), int(h));
return BAD_VALUE;
}
result = createContainerLayer(client, std::move(uniqueName), w, h, flags,
std::move(metadata), handle, &layer);
break;
default:
result = BAD_VALUE;
break;
}
//保存layer,为了surfaceflinger维护layer
result = addClientLayer(client, *handle, *gbp, layer, parentHandle, parentLayer,
addToCurrentState, outTransformHint);
if (result != NO_ERROR) {
return result;
}
//不重要
mInterceptor->saveSurfaceCreation(layer);
//binder相关
setTransactionFlags(eTransactionNeeded);
return result;
}

这段代码其实业务比较简单,通过特定的flag,生成不同的layer,然后配置layer,然后调用binder。关键是传入的flag。我们直接通过最简单的,阅读BufferQueueLayer相关代码。

status_t SurfaceFlinger::createBufferQueueLayer(const sp<Client>& client, std::string name,
uint32_t w, uint32_t h, uint32_t flags,
LayerMetadata metadata, PixelFormat& format,
sp<IBinder>* handle,
sp<IGraphicBufferProducer>* gbp,
sp<Layer>* outLayer) {
......
sp<BufferQueueLayer> layer;
LayerCreationArgs args(this, client, std::move(name), w, h, flags, std::move(metadata));
args.textureName = getNewTexture();
{
// Grab the SF state lock during this since it's the only safe way to access
// RenderEngine when creating a BufferLayerConsumer
// TODO: Check if this lock is still needed here
Mutex::Autolock lock(mStateLock);
layer = getFactory().createBufferQueueLayer(args);
}
status_t err = layer->setDefaultBufferProperties(w, h, format);
if (err == NO_ERROR) {
*handle = layer->getHandle();
*gbp = layer->getProducer();
*outLayer = layer;
}
ALOGE_IF(err, "createBufferQueueLayer() failed (%s)", strerror(-err));
return err;
}

mFactory具体类型为DefaultFactory。具体代码就比较加单了:

sp<BufferQueueLayer> DefaultFactory::createBufferQueueLayer(const LayerCreationArgs& args) {
return new BufferQueueLayer(args);
}

BufferQueueLayer 构造函数不算复杂,关键是onFirstRef的功能:

void BufferQueueLayer::onFirstRef() {
BufferLayer::onFirstRef();
// Creates a custom BufferQueue for SurfaceFlingerConsumer to use
sp<IGraphicBufferProducer> producer;
sp<IGraphicBufferConsumer> consumer;
mFlinger->getFactory().createBufferQueue(&producer, &consumer, true);
mProducer = mFlinger->getFactory().createMonitoredProducer(producer, mFlinger, this);
mConsumer =
mFlinger->getFactory().createBufferLayerConsumer(consumer, mFlinger->getRenderEngine(),
mTextureName, this);
mConsumer->setConsumerUsageBits(getEffectiveUsage(0));
mContentsChangedListener = new ContentsChangedListener(this);
mConsumer->setContentsChangedListener(mContentsChangedListener);
mConsumer->setName(String8(mName.data(), mName.size()));
// BufferQueueCore::mMaxDequeuedBufferCount is default to 1
if (!mFlinger->isLayerTripleBufferingDisabled()) {
mProducer->setMaxDequeuedBufferCount(2);
}
}

这里通过SurfaceFlinger的factory生成消费者和生产者,供给客户程序调用,我们稍微观察一下:

sp<IGraphicBufferProducer> DefaultFactory::createMonitoredProducer(
const sp<IGraphicBufferProducer>& producer, const sp<SurfaceFlinger>& flinger,
const wp<Layer>& layer) {
return new MonitoredProducer(producer, flinger, layer);
}
sp<BufferLayerConsumer> DefaultFactory::createBufferLayerConsumer(
const sp<IGraphicBufferConsumer>& consumer, renderengine::RenderEngine& renderEngine,
uint32_t textureName, Layer* layer) {
return new BufferLayerConsumer(consumer, renderEngine, textureName, layer);
}

其实这里已经介绍完毕,最终会吧BufferQueueLayer传入到客户端,生成control。最终封装成Surface。用于绘制内容。

2.3 服务端收到回复处理

客户端处理基本上就是通过binder返回的数据,构造一个SurfaceControl,这里没有特别复杂的,核心是通过SurfaceControl获取surface。

sp<Surface> SurfaceControl::getSurface() const
{
Mutex::Autolock _l(mLock);
if (mSurfaceData == nullptr) {
return generateSurfaceLocked();
}
return mSurfaceData;
}

类似与一个单利。

sp<Surface> SurfaceControl::generateSurfaceLocked() const
{
// This surface is always consumed by SurfaceFlinger, so the
// producerControlledByApp value doesn't matter; using false.
mSurfaceData = new Surface(mGraphicBufferProducer, false);
return mSurfaceData;
}

其实这里就比较简单了,关键是mGraphicBufferProducer,其实是Layer中的一个一个变量,传入到客户端了。

后记

下一篇着重分析一下mGraphicBufferProducer,的数据结构,以及如何实现跨进程数据传输的,如何吧我们的buffer交到surfaceflnger的,最后一片大概分析一下hw层,了解一下数据下传的过程,整个androidUI相关基本算是搞定。如果有机会再开一篇,介绍一下activity的窗口如何显示。

最后

以上就是阔达洋葱为你收集整理的SurfaceFlinger的渲染客户端Surface初始化的全部内容,希望文章能够帮你解决SurfaceFlinger的渲染客户端Surface初始化所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(39)

评论列表共有 0 条评论

立即
投稿
返回
顶部