surface-----surfaceflinger (createSurface)

本文详细分析了Android系统中Surface与SurfaceControl的关系及创建过程,包括SurfaceComposerClient、ISurfaceFlingerClient等关键组件的作用。

下面对Surface与SurfaceControl类之间的关系进行一下分析。

在android_view_Surface.cpp中,可以看到这样一条语句:

SurfaceComposerClient* client =

            (SurfaceComposerClient*)env->GetIntField(session, sso.client);

 

    sp<SurfaceControl> surface(client->createSurface(pid, dpy, w, h, format, flags));

 

从字面意思猜测,由SurfaceComposerClient的一个对象创建了一个Surface交由SurfaceControl进行管理。

从一些参考资料中看到,创建一个Surface的过程如下

(1)       调用libui的接口SurfaceComposerClient::CreateSurface();

(2)       调用ISurfaceFlingerClient::CreateSurface();

(3)       由于继承关系,实际上调用的是SurfaceFlinger中的接口,即BClient::CreateSurface()

(4)       继续调用SurfaceFlinger::createSurface()

我们分析下代码,看看过程是不是这样的。

跟踪到SurfaceComposerClient::createSurface中,看到这样一条语句

sp<ISurface> surface = mClient->createSurface(&data, pid,

                display, w, h, format, flags);

其中mClient是在SurfaceComposerClient中定义的一个sp<ISurfaceFlingerClient>类型的对象(还记得sp对->进行了重载吗?它其实返回了一个ISurfaceFlingerClient *)。由此可以看出,是调用的ISurfaceFlingerClient创建的Surface。而ISurfaceFlingerClient中的CreateSurface函数是一个纯虚函数,C++中,通过父类的指针可以调用子类中的函数,我们分析一下,看看在何处对mSurface进行了赋值操作,以至于产生了真正的调用。在SurfaceComposerClient::_init函数中,我们惊奇的发现,确实有一个对mSurface的赋值操作,但可惜的是,这也是将一个ISurfaceFlingerClient*类型的数赋值给了它。那它到底在什么地方进行了赋值呢?继续跟踪,找出SurfaceComposerClient::_init函数的调用者。在SurfaceComposerClient的构造函数中,有对_init函数的调用。代码如下

 

    sp<ISurfaceComposer> sm(getComposerService());

    if (sm == 0) {

        _init(0, 0);

        return;

    }

 

_init(sm, sm->createConnection());

由此,我们需要继续跟踪ISurfaceComposer中的createConnection函数,跟踪过去,竟然也是纯虚函数,杯具啊!!

 

 

在调用Surface时,调用createSurface()函数,创建各个层之后,分别调用不同层中的getSurface()接口来得到一个ISurface类型的实例,然后在SurfaceComposerClient::createSurface()中得到Surface,并将其返回。

 

3.       SurfaceFlinger和显示硬件的接口

4.       SurfaceFlinger的显示设备,是由DisplayHardware目录中的DisplayHardware.cpp文件来实现的,其中创建了一个DisplayHardware来作为主要的显示界面。

 

<think>我们正在讨论Android系统中创建Surface的相关机制,特别是SurfaceControl、SurfaceComposerClient以及像素格式设置(如PIXEL_FORMAT_RGBA_8888)。根据提供的引用,我们可以总结如下:引用[1]展示了SurfaceControl类中创建Surface对象的关键函数`generateSurfaceLocked()`。它通过`mGraphicBufferProducer`(一个`IGraphicBufferProducer`接口)创建了一个新的Surface对象,并返回该对象的强指针。这里创建的Surface将被SurfaceFlinger消费。 引用[2]和[3]则展示了在Android中使用C++创建Surface显示RGB数据的示例。引用[2]是一个Android.mk文件片段,用于编译一个名为testsurface的可执行文件,该文件依赖于libui、libgui等共享库。引用[3]则展示了如何将RGB数据(这里使用Skia库解码为RGB_565格式)显示到Surface上。 用户的问题集中在SurfaceControl和SurfaceComposerClient的使用方法,以及如何设置像素格式(如PIXEL_FORMAT_RGBA_8888)。下面我们将逐步解释这些机制。 ###1. SurfaceComposerClient`SurfaceComposerClient`是客户端与SurfaceFlinger服务通信的接口。使用它需要以下步骤:-**初始化**:首先需要创建`SurfaceComposerClient`的实例。- **连接**:调用`initCheck()`确保连接成功。 ###2. SurfaceControl`SurfaceControl`用于控制Surface的属性(如大小、格式等)和状态(如显示、隐藏等)。创建`SurfaceControl`通常通过`SurfaceComposerClient`的方法实现。 创建`SurfaceControl`的关键参数:- `width`和`height`:Surface的尺寸。 -`pixelFormat`:像素格式,例如`PIXEL_FORMAT_RGBA_8888`。- `flags`:控制Surface行为的标志,如`ISurfaceComposerClient::eHidden`(初始隐藏)等。###3.获取Surface对象通过`SurfaceControl`可以获取`Surface`对象(即`getSurface()`方法),然后就可以通过`Surface`进行绘图操作(如锁定Canvas、写入像素数据等)。 ###4.设置像素格式在创建`SurfaceControl`时,需要指定像素格式。常用的像素格式包括:- `PIXEL_FORMAT_RGBA_8888`:每个像素4字节(R、G、B、A各8位)。 -`PIXEL_FORMAT_RGB_565`:每个像素2字节(R占5位,G占6位,B占5位)。 ###示例代码以下是一个简化的示例,展示如何使用`SurfaceComposerClient`和`SurfaceControl`创建一个具有指定像素格式的Surface:```cpp#include<gui/SurfaceComposerClient.h> #include<gui/SurfaceControl.h> #include<gui/Surface.h>#include <ui/PixelFormat.h>using namespaceandroid;sp<SurfaceControl> createSurface(intwidth,int height, PixelFormat format) {//创建SurfaceComposerClientsp<SurfaceComposerClient> client= newSurfaceComposerClient();if (client->initCheck() !=NO_ERROR) {//处理错误returnnullptr;}//创建SurfaceControlsp<SurfaceControl> surfaceControl =client->createSurface(String8("MySurface"),//名称width, height,//尺寸format,//像素格式,例如PIXEL_FORMAT_RGBA_88880//标志,0表示默认可见);if(!surfaceControl ||!surfaceControl->isValid()) {//创建失败returnnullptr;}//设置Surface的位置(可选)SurfaceComposerClient::Transaction{}.setLayer(surfaceControl,INT_MAX) //设置顶层.setPosition(surfaceControl,100,100) //设置位置.show(surfaceControl)//显示.apply();returnsurfaceControl; }``` ###写入像素数据获取`Surface`对象后,可以通过锁定Canvas或直接使用`ANativeWindow_Buffer`来写入像素数据:```cppsp<Surface> surface= surfaceControl->getSurface(); ANativeWindow_Bufferbuffer;ARect rect;status_tstatus =surface->lock(&buffer,&rect); if(status== NO_ERROR){//根据像素格式写入数据if(buffer.format ==PIXEL_FORMAT_RGBA_8888){uint32_t*pixels =static_cast<uint32_t*>(buffer.bits);//填充RGBA数据...}surface->unlockAndPost(); }``` ###注意事项-权限:应用需要`android.permission.ACCESS_SURFACE_FLINGER`权限(系统应用)。 -线程安全:确保在正确的线程中操作(通常为应用的主线程)。-像素格式转换:如果输入数据格式与Surface格式不一致,需要转换(如引用[3]中Skia库将图像解码为RGB_565)。###调试建议-使用`dumpsysSurfaceFlinger`命令查看当前Surface状态。 -检查`logcat`输出,特别是`SurfaceFlinger`和`GraphicBuffer`相关日志。§§相关问题§§1. Android中如何使用`SurfaceComposerClient`创建多个Surface?2.`PIXEL_FORMAT_RGBA_8888`与`PIXEL_FORMAT_RGBX_8888`有何区别? 3.如何将图像数据(如PNG、JPEG)绘制到AndroidSurface上? 4.在创建Surface时,`SurfaceComposerClient::Transaction`还能设置哪些属性?5.如何捕获SurfaceFlinger的日志以调试Surface创建问题?</think>### Android Surface创建机制解析 在Android系统中,创建Surface涉及`SurfaceComposerClient`和`SurfaceControl`两个核心类,以及像素格式(如`PIXEL_FORMAT_RGBA_8888`)的设置。以下是关键步骤和原理: --- ### **1. 核心组件关系** ```mermaid graph LR A[SurfaceComposerClient] -->|创建| B[SurfaceControl] B -->|生成| C[Surface] C -->|关联| D[IGraphicBufferProducer] D -->|传递| E[SurfaceFlinger] ``` - **SurfaceComposerClient**:客户端与SurfaceFlinger服务的桥梁 - **SurfaceControl**:Surface的控制器,管理属性和生命周期 - **Surface**:实际绘图表面,持有`IGraphicBufferProducer` --- ### **2. 创建流程(C++示例)** #### (1) 初始化SurfaceComposerClient ```cpp sp<SurfaceComposerClient> client = new SurfaceComposerClient(); client->initCheck(); // 验证连接状态 ``` #### (2) 创建SurfaceControl ```cpp sp<SurfaceControl> surfaceControl = client->createSurface( String8("MySurface"), // Surface名称 width, height, // 尺寸 PIXEL_FORMAT_RGBA_8888, // 像素格式 0 // 标志位 ); ``` **关键参数说明**: - **像素格式**: - `PIXEL_FORMAT_RGBA_8888`:每像素32位(8位/通道) - 其他选项:`RGB_565`(16位),`RGBA_F16`(HDR)等 - **标志位**: - `ISurfaceComposerClient::eHidden`:初始隐藏 - `ISurfaceComposerClient::eOpaque`:不透明Surface #### (3) 获取Surface对象 ```cpp sp<Surface> surface = surfaceControl->getSurface(); ``` 此过程会调用`generateSurfaceLocked()`[^1],创建关联`IGraphicBufferProducer`的Surface对象。 #### (4) 配置Surface属性(Transaction) ```cpp SurfaceComposerClient::Transaction t; t.setLayer(surfaceControl, INT_MAX); // 设置层级(顶层) t.setPosition(surfaceControl, x, y); // 设置位置 t.show(surfaceControl); // 显示Surface t.apply(); // 提交事务 ``` --- ### **3. 写入RGB数据** 获取Surface后,可通过以下方式写入RGBA数据: ```cpp // 锁定Surface进行绘制 ANativeWindow_Buffer buffer; surface->lock(&buffer, nullptr); uint32_t* pixels = static_cast<uint32_t*>(buffer.bits); // 填充RGBA数据(示例:红色) const int pixelCount = buffer.width * buffer.height; for (int i = 0; i < pixelCount; ++i) { pixels[i] = 0xFFFF0000; // AARRGGBB格式 } // 提交数据 surface->unlockAndPost(); ``` > 注意:需确保数据布局与`PIXEL_FORMAT_RGBA_8888`的`AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM`格式匹配[^3]。 --- ### **4. 像素格式详解** | 格式常量 | 位深度 | 内存布局 | 适用场景 | |--------------------------|--------|-------------------|-------------------| | `PIXEL_FORMAT_RGBA_8888` | 32bpp | R-G-B-A (各8位) | 通用UI/透明效果 | | `PIXEL_FORMAT_RGBX_8888` | 32bpp | R-G-B-X (无Alpha) | 不透明内容 | | `PIXEL_FORMAT_RGB_565` | 16bpp | R(5)-G(6)-B(5) | 低内存消耗场景[^3] | --- ### **5. 常见问题排查** 1. **创建失败**: - 检查`initCheck()`返回值 - 验证`android.permission.ACCESS_SURFACE_FLINGER`权限 2. **显示异常**: - 确认像素格式与数据写入格式一致 - 检查`Transaction`是否成功提交(`apply()`调用) 3. **性能优化**: - 使用`AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE`标志启用GPU加速 - 避免频繁`lock/unlock`,批量更新数据 > 调试建议:通过`dumpsys SurfaceFlinger`命令查看Surface状态[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值