1.Android 14 HWUI 源码研究 View Canvas RenderThread ViewRootImpl skia
2.wxsqlite静态编译 sqlite3加密 的源码简单方法
3.skia发展历史
4.Flutter 新一代图形渲染器 Impeller
Android 14 HWUI 源码研究 View Canvas RenderThread ViewRootImpl skia
HUWUI是Android系统中负责应用可视化元素绘制的核心组件,其架构主要在C++层实现,下载从Java层接收View绘制信息,源码通过唯一的下载渲染线程使用skia技术完成渲染任务。整体上,源码从应用程序到UI线程,下载linux ss 源码再到渲染线程,源码形成了清晰的下载层级关系。
HUWUI的源码构建主要包括三个核心类,它们分别是下载:RecordingCanvas、Canvas、源码RenderNode、下载RenderProxy、源码RenderThread、下载CanvasContext、源码IRenderPipeline。在Java层,主要涉及两类Canvas,RecordingCanvas用于记录绘制指令,Canvas则是直接用于渲染。RecordingCanvas在构造时创建,而Canvas在调用时创建。这两个类在C++层分别对应SkiaRecordingCanvas和SkiaCanvas,后者直接引用SkCanvas。webapi vue源码
在全局循环中,UI线程与渲染线程之间的协同操作至关重要。具体流程包括:新创建Activity后,附着到对应的PhoneWindow,然后调用PhoneWindow的setContentView方法,将View添加到DecorView作为子节点。接着,DecorView与ViewRootImpl对接,完成View的更新与渲染。整个过程包含了measure、layout和draw等复杂子流程。
渲染线程创建与核心对象紧密关联,主要包括RenderProxy、RenderThread和DrawFrameTask。RenderProxy负责Java层信息的衔接,RenderThread作为进程唯一的渲染线程,持有DrawFrameTask和CanvasContext,完成一帧的绘制任务。指令记录流程的核心在于使用C++层的RecordingCanvas将View属性和绘制信息记录到DisplayList中,进而完成指令的渲染。
Surface、ANativeWindow、EGLSurface的wifidog计费源码创建流程在ViewRootImpl的performTraversals函数中初始化。ReliableSurface的封装和EGL与Skia环境的创建主要在RenderThread的requireGlContext函数中实现。从源码分析,这一过程通常在三个地方调用。
View树与RenderNode树之间的协作关系明确,一个Application进程对应多个Activity,每个Activity与一个PhoneWindow绑定,PhoneWindow持有DecorView,DecorView对应一个ViewRootImpl,而ViewRootImpl与ThreadedRender模块对接。ThreadedRender与C++层的RenderProxy一一对应,RenderProxy持有关键对象,如RenderThread、CanvasContext、DrawFrameTask等。RenderThread是单例模式,进程唯一,负责一帧绘制的逻辑。
在RenderPipeline模块中,关键操作包括makeCurrent、draw和swapBuffers。Native Canvas在这一过程中扮演了桥梁角色,接收Java API调用,而RecordingCanvas完成Op记录,每天搜索源码最终DisplayListData存储这些Op。
skia的核心资源主要在三个使用场景中发挥作用,具体细节需深入分析,这些资源对于实现高效、稳定的渲染效果至关重要。
wxsqlite静态编译 sqlite3加密 的简单方法
针对需要在项目中集成sqlite3加密功能的需求,可选择wxsqlite作为解决方案。相较于其他推荐的工具,wxsqlite提供了更为简便的静态编译方式。
通过使用xmake作为包管理器,发现wxsqlite的集成相对简单,无需面对复杂的库文件与配置问题。选择wxsqlite的理由在于其提供了合并的C文件,只需将其包含至项目中即可。
首先,下载wxsqlite源码,并在对应的目录下找到需要的两个文件。这些文件是wxsqlite的关键组成部分,直接将它们加入到项目内即可实现功能集成。
在构建系统中,只需简单配置,添加必要的包含路径,即可实现wxsqlite的种植助力源码静态编译。整个过程简洁高效,无需面对繁琐的库文件管理和复杂配置。
在项目中直接包含头文件,使用wxsqlite的加密功能即可。对于设置选项,通常默认配置已能满足基本需求,无需额外调整。
使用wxsqlite后,可发现程序的执行文件大小略有增加,例如,加入SDL2后,执行文件大小增加了2M,加入skia后,增加了7、8M。这些额外的大小主要源自于所集成的额外依赖库。
针对不需进行图形绘制的情况,可选择使用SVG格式替代,通过SDL_image库处理SVG文件,同样可以实现所需的视觉效果。这种方法在简化代码的同时,也减少了依赖库的使用,进一步优化了项目的大小。
总体而言,通过wxsqlite实现sqlite3加密功能的过程简单明了,无需面对复杂的编译与配置问题。对于游戏项目而言,即使执行文件大小有所增加,对于整体的资源占用来说仍然属于较小的影响。
使用wxsqlite后,观察到编译后的执行文件大小相较于其他方法,保持在合理的范围内,通常在1M以上。这表明在集成wxsqlite时,已较好地控制了对项目资源的影响。
skia发展历史
自年Google购入Skia以来,这个项目一直保持着相对低调的姿态。转折点发生在年初,Skia的GL相关源代码首次公开,它成为了Google Android平台的关键图形引擎。随后,Google Chrome浏览器也接纳了Skia的技术,使其在浏览器渲染中发挥重要作用。随着Android和Chrome开源计划(Android的开源版本称为Chromium)的展开,Skia的原始源代码也随之公开,采用的是Apache License v2的许可协议,这与GPLv2有所不同。在Android和Chrome的源代码库中,都包含了对Skia的定制版本,如Chrome项目下的"chrome/trunk/src/skia",这些定制主要针对各自平台的需求,如Android通过Linux Framebuffer接口与系统集成,而Chrome在开发中的Linux版本则使用Gtk+。
值得注意的是,Skia本身并不直接处理底层环境的细节,如Linux Framebuffer或Gtk+的衔接,这就导致了Android和Chrome需要针对其各自的环境需求进行相应的代码修改,以确保系统的兼容性和流畅运行。这些定制版的Skia在各自的项目中扮演了不可或缺的角色,但原始的Skia项目本身并未涉及这些底层整合工作。[1]
Flutter 新一代图形渲染器 Impeller
Flutter在年的Roadmap中提出需重新考虑着色器使用方式,计划重写图像渲染后端。此计划的初步成果是名为Impeller的渲染后端,本文将探讨Impeller解决的问题、目标、架构和渲染细节。
背景部分, Flutter过去一年解决了不少Jank问题,但着色器编译导致的Jank问题一直没有解决。着色器编译Jank问题源于Flutter底层使用skia做2D图形渲染库,内部定义了SkSL(Skia shading language)。在光栅化阶段,skia生成SkSL着色器,再将其转换为特定后端(GLSL、GLSL ES 或 Metal SL)着色器,并在设备上编译,此过程可能耗时数百毫秒,导致数十帧丢失。通过在Flutter 1.版本中为GL后端实现SkSL预热机制,离线收集并保存应用程序中使用的SkSL着色器,进而提升性能。
Impeller架构部分,Impeller是专为Flutter设计的渲染器,目前处于早期原型阶段,仅支持iOS和Mac系统,依赖flutter fml和display list,并实现了display list dispatcher接口,便于替换skia。其核心目标是解决着色器编译Jank问题。
Impeller着色器离线编译部分,Impeller compiler模块是关键。在编译阶段,将compiler相关源码编译为host工具impellerc binary,利用impellerc compiler将所有着色器源码(包括顶点和片段着色器)编译为SPIR-V中间语言,再转换为特定后端的高级着色器语言(如Metal SL),并编译为shader library,同时生成C++ shader binding用于快速创建pipeline state objects。这样所有着色器在离线时被编译,运行时不需执行任何编译操作,提升首帧渲染性能。
Impeller渲染流程部分,通过继承IOSContext、IOSSurface和flow Surface实现IOSContextMetalImpeller、IOSSurfaceMetalImpeller和GPUSurfaceMetalImpeller结构,对接flutter flow子系统。光栅化阶段,通过DisplayListCanvasRecorder合成Layer Tree,将所有layer中的绘图命令转换为DLOps,并存储到DisplayList结构。随后,使用DisplayListDispatcher执行所有Ops,将信息转换为EntityPass结构。接着,使用RenderPass从Root EntityPass开始遍历,将每个Entity转换为Command结构,生成GPU Pipeline,设置顶点和片段着色器的数据,将顶点数据和颜色或纹理数据转换为GPU buffer。最后,开始渲染指令编码阶段,根据MTLCommandBuffer生成MTLRenderCommandEncoder,遍历所有Commands,设置PipelineState、Vertext Buffer和Fragment Buffer,提交command buffer。
总结部分,Impeller通过离线编译着色器、优化渲染流程等手段解决着色器编译Jank问题,显著提升渲染性能。Flutter重写图像渲染后端的决心可见一斑,期待Impeller能进一步提升Flutter的渲染性能。