欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 财经 > 产业 > Android显示系统(11)- 向SurfaceFlinger申请Surface

Android显示系统(11)- 向SurfaceFlinger申请Surface

2025/6/26 19:23:06 来源:https://blog.csdn.net/Ziwubiancheng/article/details/144445796  浏览:    关键词:Android显示系统(11)- 向SurfaceFlinger申请Surface

Android显示系统(01)- 架构分析
Android显示系统(02)- OpenGL ES - 概述
Android显示系统(03)- OpenGL ES - GLSurfaceView的使用
Android显示系统(04)- OpenGL ES - Shader绘制三角形
Android显示系统(05)- OpenGL ES - Shader绘制三角形(使用glsl文件)
Android显示系统(06)- OpenGL ES - VBO和EBO和VAO
Android显示系统(07)- OpenGL ES - 纹理Texture
Android显示系统(08)- OpenGL ES - 图片拉伸
Android显示系统(09)- SurfaceFlinger的使用
Android显示系统(10)- SurfaceFlinger内部结构
Android显示系统(11)- 向SurfaceFlinger申请Surface
Android显示系统(12)- 向SurfaceFlinger申请Buffer
Android显示系统(13)- 向SurfaceFlinger提交Buffer

一、前言:

前面已经和SurfaceFlinger建立好了连接,那么,本章介绍下如何去向SurfaceFlinger申请我们的画布(也就是Surface)。

二、获取Surface流程:

上面创建好了Client,也就是创建好了连接,我们要绘制一张图片,首先得拿到画布,这个由CreateSurface完成:

status_t BootAnimation::readyToRun() {// 。。。// 创建SurfaceControl, 参数指定名称 ("BootAnimation")、宽度、高度和像素格式 (PIXEL_FORMAT_RGB_565)sp<SurfaceControl> control = session()->createSurface(String8("BootAnimation"),dinfo.w, dinfo.h, PIXEL_FORMAT_RGB_565);SurfaceComposerClient::Transaction t;t.setLayer(control, 0x40000000).apply();// 获得对应的Surface(画布)sp<Surface> s = control->getSurface();// 。。。
}

可以看出,先获取SurfaceControl,然后从SurfaceControl当中取出了Surface,那么,这个API调用,后面都有谁在配合呢?

1、APP侧开始请求:

这个session()里面其实就是返回一个mSession,我们都知道mSessionsp<SurfaceComposerClient>类型,进去看看:

sp<SurfaceControl> SurfaceComposerClient::createSurface(const String8& name, uint32_t w, uint32_t h,PixelFormat format, uint32_t flags,SurfaceControl* parent,LayerMetadata metadata) {sp<SurfaceControl> s;createSurfaceChecked(name, w, h, format, &s, flags, parent, std::move(metadata));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) {sp<SurfaceControl> sur;status_t err = mStatus;if (mStatus == NO_ERROR) {sp<IBinder> handle; // Surfacesp<IBinder> parentHandle;sp<IGraphicBufferProducer> gbp; // SF端Layer的生产者对象if (parent != nullptr) {parentHandle = parent->getHandle();}// 这个mClienterr = mClient->createSurface(name, w, h, format, flags, parentHandle, std::move(metadata),&handle, &gbp);ALOGE_IF(err, "SurfaceComposerClient::createSurface error %s", strerror(-err));if (err == NO_ERROR) {// 创建SurfaceControl*outSurface = new SurfaceControl(this, handle, gbp, true /* owned */);}}return err;
}

前面说过,这个mClient其实就是BpSurfaceComposer,所以,这个函数就是先远程调用SF获取了一个Surface(通过handle返回),并且呢,用一个SurfaceControl将这个Surface持有并管理起来。

BpSurfaceComposerClient当中发起远程调用:

 status_t createSurface(const String8& name, uint32_t width, uint32_t height, PixelFormat format,uint32_t flags, const sp<IBinder>& parent, LayerMetadata metadata,sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp) override {return callRemote<decltype(&ISurfaceComposerClient::createSurface)>(Tag::CREATE_SURFACE,name, width, height,format, flags, parent,std::move(metadata),handle, gbp);}

记住这个Tag::CREATE_SURFACE,发起Binder远程调用之后,SF侧就会根据这个id来处理。

2、SurfaceFlinger侧响应:

  • 简单调用逻辑传递:

binder调用部分省略,参考上一章的createConnection,然后就来到了:

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) {// We rely on createLayer to check permissions.return mFlinger->createLayer(name, this, w, h, format, flags, std::move(metadata), handle, gbp,parentHandle);
}

这就相当于什么?相当于客户端调用了一个createSurface,到了服务端调用了Client::createSurface,里面进行了Layer的创建。

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) {sp<Layer> layer;//...switch (flags & ISurfaceComposerClient::eFXSurfaceMask) {// 就是普通Surfacecase ISurfaceComposerClient::eFXSurfaceBufferQueue:result = createBufferQueueLayer(client, uniqueName, w, h, flags, std::move(metadata),format, handle, gbp, &layer);break;case ISurfaceComposerClient::eFXSurfaceBufferState:result = createBufferStateLayer(client, uniqueName, w, h, flags, std::move(metadata),handle, &layer);break;case ISurfaceComposerClient::eFXSurfaceColor:// 。。。case ISurfaceComposerClient::eFXSurfaceContainer:// 。。。default:result = BAD_VALUE;break;}if (primaryDisplayOnly) {layer->setPrimaryDisplayOnly();}bool addToCurrentState = callingThreadHasUnscopedSurfaceFlingerAccess();result = addClientLayer(client, *handle, *gbp, layer, parentHandle, parentLayer,addToCurrentState);if (result != NO_ERROR) {return result;}mInterceptor->saveSurfaceCreation(layer);setTransactionFlags(eTransactionNeeded);return result;
}

对于上面的switch…case,我们为啥走第一个呢?我给你加了注释:

    enum { // (keep in sync with Surface.java)// 表示 Surface 默认状态是隐藏的, 用于需要控制 Surface 显示/隐藏状态的情况,例如临时用来后台渲染内容的 SurfaceeHidden = 0x00000004,// 指示在销毁表面时是否销毁后备缓冲区。不适合需要保留屏幕内容的情况eDestroyBackbuffer = 0x00000020,// 表示 Surface 是安全的,意味着内容只能显示在安全的显示器上(如受保护的 HDMI 输出)eSecure = 0x00000080,// 表示创建的表面使用非预乘的像素格式eNonPremultiplied = 0x00000100,// 如果设置了该标志,Surface 将忽略 alpha 通道,像素总是完全不透明的eOpaque = 0x00000400,// Surface 内容由应用保护。内容通常是敏感数据,应用负责其生命周期eProtectedByApp = 0x00000800,// 表示 Surface 受到 DRM(数字版权管理)保护,通常通过硬件实现。eProtectedByDRM = 0x00001000,// 表示 Surface 用作光标窗口。系统级别的输入指针,比如鼠标指针。eCursorWindow = 0x00002000,// 表明这是一个普通的 BufferQueue Surface(默认设置,无附加特性)。创建普通的 Surface。eFXSurfaceBufferQueue = 0x00000000,// 表示这是一个颜色缓冲区的 Surface,可能用于特殊效果(如着色器)。eFXSurfaceColor = 0x00020000,// 允许使用不同的 buffer 管理策略(如摆脱传统的 BufferQueue 行为)。eFXSurfaceBufferState = 0x00040000,// 表示这是一个 "容器 Surface",用来包裹其他子 Surface。窗口管理器或复杂 Layer。eFXSurfaceContainer = 0x00080000,// 一个掩码 (mask),表示 eFXSurface* 类 Surface 的通用标志。eFXSurfaceMask = 0x000F0000,};

显然,我们就是一个普通的surface;

  • 创建Layer的过程:

    status_t SurfaceFlinger::createBufferQueueLayer(const sp<Client>& client, const String8& name,uint32_t w, uint32_t h, uint32_t flags,LayerMetadata metadata, PixelFormat& format,sp<IBinder>* handle,sp<IGraphicBufferProducer>* gbp,sp<Layer>* outLayer) {// initialize the surfacesswitch (format) {case PIXEL_FORMAT_TRANSPARENT:case PIXEL_FORMAT_TRANSLUCENT:format = PIXEL_FORMAT_RGBA_8888;break;case PIXEL_FORMAT_OPAQUE:format = PIXEL_FORMAT_RGBX_8888;break;}// 创建了一个Layersp<BufferQueueLayer> layer = getFactory().createBufferQueueLayer(LayerCreationArgs(this, client, name, w, h, flags, std::move(metadata)));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;
    }
    

    看到创建Layer成功之后,便将Layer的handle,以及Layer的BufferQueueProducer返回,同时,也将layer本身返回给outLayer。

    那么,这个工厂是如何创建这个Layer的呢?

    看看文件native\services\surfaceflinger\SurfaceFlingerFactory.cpp中:

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

    就是new了一个,返回而已,我们第一个引用Layer时候会发生什么?

    void BufferQueueLayer::onFirstRef() {BufferLayer::onFirstRef();// Creates a custom BufferQueue for SurfaceFlingerConsumer to usesp<IGraphicBufferProducer> producer;sp<IGraphicBufferConsumer> consumer;// 创建BufferQueue的时候,里面会创建生产者和消费者BufferQueue::createBufferQueue(&producer, &consumer, true);// 将消费者做一次封装mProducer = new MonitoredProducer(producer, mFlinger, this);{// Grab the SF state lock during this since it's the only safe way to access RenderEngine// 同样,将生产者做一次封装Mutex::Autolock lock(mFlinger->mStateLock);mConsumer =new BufferLayerConsumer(consumer, mFlinger->getRenderEngine(), mTextureName, this);}mConsumer->setConsumerUsageBits(getEffectiveUsage(0));mConsumer->setContentsChangedListener(this);mConsumer->setName(mName);// BufferQueueCore::mMaxDequeuedBufferCount is default to 1if (!mFlinger->isLayerTripleBufferingDisabled()) {mProducer->setMaxDequeuedBufferCount(2);}if (const auto display = mFlinger->getDefaultDisplayDevice()) {updateTransformHint(display);}
    }
    

    主要就是创建了一个BufferQueueProducerConsumer

  • 刚才看到生产者和消费者都继承自IGraphicBufferProducer,我们看下:

    在这里插入图片描述

    • APP这边的BpGraphicBufferProducer和 Native那边的Client的Layer成员的mProducer,都继承自IGraphicBufferProducer
    • 不过Native最终使用的是IGraphicBufferProducer派生的BnGraphicBufferProducer派生的BnBufferQueueProducer

于是,我们再回去看看APP侧如何处理返回的这些东西。

3、APP侧处理返回值:

直接看代码:

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) {sp<SurfaceControl> sur;status_t err = mStatus;if (mStatus == NO_ERROR) {sp<IBinder> handle; // Surfacesp<IBinder> parentHandle;sp<IGraphicBufferProducer> gbp; // SF端Layer的生产者对象if (parent != nullptr) {parentHandle = parent->getHandle();}// 这个mClienterr = mClient->createSurface(name, w, h, format, flags, parentHandle, std::move(metadata),&handle, &gbp);ALOGE_IF(err, "SurfaceComposerClient::createSurface error %s", strerror(-err));if (err == NO_ERROR) {// 创建SurfaceControl*outSurface = new SurfaceControl(this, handle, gbp, true /* owned */);}}return err;
}

发现将创建好的handle、gdp全都作为参数用来创建SurfaceControl了。进去看看:

SurfaceControl::SurfaceControl(const sp<SurfaceComposerClient>& client,const sp<IBinder>& handle,const sp<IGraphicBufferProducer>& gbp,bool owned): mClient(client), mHandle(handle), mGraphicBufferProducer(gbp), mOwned(owned)
{
}

发现构造函数直接将gbp保存到mGraphicBufferProducer当中了。啥时候用呢?

当你从SurfaceControl获取Surface的时候:

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

看看这个generateSurfaceLocked

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;
}

发现生成Surface的时候,gbp是入参,也就是说这个Buffer的生产者已经被我们Surface持有了,以后可以通过Surface往SF侧的Layer当中BufferQueue写东西。

三、总结:

至此,Surface获取部分讲解完成,拿到画布之后该往里填数据了吧?

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词