跨平台Web Canvas渲染引擎架构的设计与思考(内含实现方案)


工作原理其实比较简单,一句话就可以说明白。首先封装图形API(OpenGL、Vulkan、Metal…)以支持WebGL和Canvas 2D矢量图渲染能力,对下桥接到不同操作系统和容器之上,对上通过language binding将渲染能力以标准化接口透出到业务容器的JS上下文。

举个例子,以下是淘宝小程序容器Canvas组件的渲染流程,省略了「亿」点点细节。

Canvas在Android上其实是一个SurfaceView/TextureView,通过同层渲染的方式嵌入到UCWebView中。开发者调用Canvas JS接口,最终会生成一系列的渲染指令送到GPU,渲染结果写入图形缓冲区,在合适时机通过SwapBuffer交换缓冲区,然后操作系统进行图层合成和送显。

  分层架构

从业务形态上看,不管是小程序、小游戏还是其他容器,实现上都是相似的,如下图所示,通过JSBinding实现标准Canvas接口,开发者可以通过适配在上面跑web游戏引擎(laya、egret、threejs…),下边是JS引擎,这一层可以有不同的技术选型,如老牌的V8、JSC,后起之秀quickjs、hermes等等,在这之下就是Canvas核心实现了,这一层需要分别提供WebGL、Canvas2D的能力。WebGL较为简单,基本与OpenGLES接口一一对应,简单封装即可。

Canvas 2D如果要从零开始实现的话相对来说会复杂一些(特别是文字、图片、路径的渲染等),不过技术选型上仍然有很多选择比如cairo、skia、nanovg等等,不管使用哪种方案,只要是硬件渲染,其backend只有vulkan/OpenGLES/metal/Direct3D等几种选择。

目前OpenGL使用最为广泛,还可以通过google的Angle项目适配到vulkan/directx等不同backend上。Canvas实现层之下是WAL窗体抽象层,这一层的职责就是为渲染提供宿主环境,通过EGL/EAGL等方式绑定GL上下文与平台窗体系统。下文将对相关模块的实现分别进行介绍。考虑到性能、可移植性等因素,除了与平台/容器桥接的部分需要使用OC/Java等语言实现之外,其余部分基本采用C++实现。

JS Binding机制

JS引擎通常会抽象出VM、JSContext、JSValue、GlobalObject等概念,VM代表一个JS虚拟机实例,拥有独立的堆栈空间,有点类似进程的概念,不同的VM相互是隔离的(因此在v8中以v8::Isolate命名),一个VM中可以有多个JSContext,JSContext代表一个JS的执行上下文,可以执行JS代码,JSValue代表一个JS值类型,可以是基础数据类型也可以是Object类型,每个JSContext中都会拥有一个GlobalObject对象,GlobalObject在JSContext整个生命周期内,都可以直接进行访问,它默认是可读可写的,因此可以在GlobalObject上绑定属性或者函数等,这样就可以在JSContext执行上下文中访问它们了。

要想在JS环境中使用Canvas,需要将Canvas相关接口注入到JS环境,正如Java JNI、Python Binding、Lua Binding等类似,JS引擎也提供了Extension机制,称之为JS Binding,它允许开发者使用c++等语言向JS上下文中注入变量、函数、对象等。

// V8函数绑定示例

static void LogCallback(const v8::FunctionCallbackInfov8::Value& args){…}

// Create a template for the global object and set the

// built-in global functions.

v8::Localv8::ObjectTemplate global = v8::ObjectTemplate::New(isolate);

global->Set(v8::String::NewFromUtf8(isolate, “log”),

v8::FunctionTemplate::New(isolate, LogCallback));

// Each processor gets its own context so different processors

// do not affect each other.

v8::Persistentv8::Context context =

v8::Context::New(isolate, nullptr, global);

以小程序环境为例,小程序容器初始化时,会分别创建Render和Worker,Render负责界面渲染,Worker负责执行业务逻辑,拥有独立JSContext,Canvas提

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值