显示系统HWUI与SurfaceFlinger 交互机理以及关键代码分析
}}(3)提交软件绘制结果 cpp// Surface.cpp:软件绘制后的 Buffer 提交status_t Surface::unlockAndPostSoftwareBuffer(SkBitmap* bitmap) {// 1. 将 Skia 绘制后的像素数据拷贝到 Surface 的 Buffermemcpy(mCurrentBuffer->bits(), bitmap->getPixe

一、SurfaceView 与普通 View 的绘制差异(结合 HWUI/SurfaceFlinger 交互)
-
核心差异本质 - 普通 View:共享 Activity 的 Surface,HWUI 绘制后提交到 Activity 对应的 BufferQueue,SurfaceFlinger 会将其作为一个图层与其他 View 图层合成。- SurfaceView:拥有 独立 Surface,直接与 SurfaceFlinger 建立 BufferQueue 连接,HWUI 绘制的 Buffer 单独提交,SurfaceFlinger 单独处理该图层(可实现分层渲染、硬件叠加)。
-
代码差异对比(HWUI 侧)
(1)普通 View 绘制(共享 Surface) java
// 底层由 Activity 的 Window 提供 Surface,HWUI 绘制后提交到共享 BufferQueue@Overrideprotected void onDraw(Canvas canvas) { super.onDraw(canvas); canvas.drawText(“普通 View 绘制”, 100, 100, paint); // 无需手动解锁提交,HWUI 自动处理,最终通过 Window 的 Surface 提交给 SurfaceFlinger}
(2)SurfaceView 绘制(独立 Surface) java // 1. 获取独立 Surface 的 HolderSurfaceHolder holder = surfaceView.getHolder();holder.addCallback(new SurfaceHolder.Callback() { @Override public void surfaceCreated(SurfaceHolder holder) { // 2. 独立 Surface 可用,获取 Canvas(HWUI 实现) Canvas canvas = holder.lockCanvas(null); // 3. HWUI 绘制(独立缓冲区) canvas.drawText(“SurfaceView 独立绘制”, 100, 100, paint); // 4. 解锁提交,直接发送到 SurfaceView 专属 BufferQueue holder.unlockCanvasAndPost(canvas); } // surfaceChanged、surfaceDestroyed 回调处理尺寸变化和资源释放}); 3. SurfaceFlinger 侧处理差异 - 普通 View:SurfaceFlinger 接收的是 Activity 图层的整体 Buffer,需解析 View 层级进行内部合成。- SurfaceView:SurfaceFlinger 接收 独立 Buffer,可通过 HWC(硬件合成器) 直接叠加到屏幕,无需与 Activity 图层软件合成,效率更高(适合视频、游戏等高频绘制场景)。二、BufferQueue 的缓冲区回收机制(核心交互闭环) 1. 回收流程(生产者-消费者模型) 1. HWUI 生产 Buffer:HWUI 锁定 Surface 后,从 BufferQueue 申请空闲 Buffer( dequeueBuffer ),绘制完成后提交( queueBuffer ),此时 Buffer 状态变为“已提交”。2. SurfaceFlinger 消费 Buffer:SurfaceFlinger 读取 Buffer 完成合成后,通过 releaseBuffer 将 Buffer 归还给 BufferQueue,状态重置为“空闲”。3. 循环复用:HWUI 下次绘制时重复申请空闲 Buffer,形成闭环。 2. 核心代码(BufferQueue 底层逻辑,C++) cpp // BufferQueue 生产者侧(HWUI 调用)status_t BufferQueueProducer::dequeueBuffer(int* outBuf, …) { // 查找空闲 Buffer,标记为“已分配” for (size_t i = 0; i < mBuffers.size(); ++i) { if (mBuffers[i].mState == BufferSlot::FREE) { *outBuf = i; mBuffers[i].mState = BufferSlot::DEQUEUED; return NO_ERROR; } } return WOULD_BLOCK; // 无空闲 Buffer 时阻塞(或返回错误)}// BufferQueue 消费者侧(SurfaceFlinger 调用)status_t BufferQueueConsumer::releaseBuffer(int buf, …) { // 回收 Buffer,重置状态为空闲 if (mSlots[buf].mState == BufferSlot::ACQUIRED) { mSlots[buf].mState = BufferSlot::FREE; // 通知生产者(HWUI)有新空闲 Buffer mProducerListener->onBufferReleased(); return NO_ERROR; } return BAD_VALUE;} 3. 关键优化点 - 缓冲区数量:默认 2-3 个 Buffer(双缓冲/三缓冲),避免 HWUI 绘制等待 SurfaceFlinger 消费。- 超时机制:若 SurfaceFlinger 长期不消费,BufferQueue 会强制回收 Buffer,防止内存泄漏。
三、HWUI 处理 Buffer 分配失败的核心逻辑 1. 失败场景与触发条件 Buffer 分配失败多因 内存不足 或 缓冲区全部被占用(SurfaceFlinger 消费慢于 HWUI 生产),HWUI 会通过「重试+降级」机制保证绘制不崩溃。 2. 核心代码(HWUI 侧,Java/C++ 结合) java // 上层:Surface 锁定 Buffer 时的失败处理(Surface.java)public Canvas lockCanvas(Rect inOutDirty) throws Surface.OutOfResourcesException { try { // 底层调用 nativeLockCanvas,申请 Buffer return nativeLockCanvas(mNativeObject, inOutDirty); } catch (OutOfResourcesException e) { // 1. 重试机制:等待 50ms 后重试 1 次 try { Thread.sleep(50); return nativeLockCanvas(mNativeObject, inOutDirty); } catch (InterruptedException | OutOfResourcesException ex) { // 2. 重试失败:触发降级策略 return getFallbackCanvas(); // 降级为软件绘制的 Canvas } }}// 底层:Native 层 Buffer 申请(Surface.cpp)status_t Surface::lock(ANativeWindow_Buffer* outBuffer, …) { // 调用 BufferQueueProducer 申请 Buffer status_t result = mProducer->dequeueBuffer(&buf, &fence, …); if (result == WOULD_BLOCK) { // 无空闲 Buffer,抛出异常给上层 return NO_MEMORY; } // 分配成功,返回 Buffer 给 HWUI 绘制 return mapBufferLocked(buf, outBuffer);} 3. 降级策略细节 - 若重试后仍分配失败,HWUI 会创建 软件 Canvas(Skia 纯软件绘制),绕过硬件加速,牺牲性能但保证绘制完成。- 同时触发系统内存回收(通过 Runtime.getRuntime().gc() ),为后续 Buffer 分配释放空间。
四、SurfaceFlinger 硬件合成(HWC)具体逻辑 1. HWC 核心作用 HWC(Hardware Composer)是硬件抽象层组件,负责将 符合条件的图层直接通过硬件叠加,替代 OpenGL 软件合成,提升效率(尤其多图层、高分辨率场景)。 2. 核心流程与代码(C++) (1)图层筛选(判断是否支持硬件合成) cpp // SurfaceFlinger.cpp:合成前筛选 HWC 支持的图层void SurfaceFlinger::prepareHwcLayers() { for (auto& layer : mLayers) { auto hwcLayer = layer->getHwcLayer(); // 筛选条件:图层格式(如 RGBA_8888)、缩放比例、叠加顺序支持硬件处理 if (layer->supportsHardwareCompositing()) { hwcLayer->setCompositionType(HWC2::Composition::DEVICE);
------------+++++++
完整分享请关注微信公众号:颇锐克科技共享,进行获取。
__++++++++++++(((
更多AI,GPU,Linux,Android,芯片行业技术分享请关注公众号:颇锐克科技共享。
火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。
更多推荐
所有评论(0)