Taobao FED

GCanvas 渲染引擎介绍

GCanvas 渲染引擎介绍

GCanvas 提供了一套类似于 H5 Canvas 标准的 JavaScript API。基于这套 API 可以方便的去做图形绘制、动画渲染等,开发的体验与 H5 Canvas 是完全一样的。

GCanvas 介绍

GCanvas发展经历了两个阶段。

  • 第一阶段,2014 年中到 2015 年底,解决 Android 平台 WebView Canvas 渲染性能差的问题。
  • 第二阶段,2016 年 11 月到现在,为前端提供 Native 图形绘制能力。

用一句话来概括 GCanvas,即遵循 W3C 标准,移动端的跨平台的高性能图形渲染引擎。可以从三个方面来解释。

  • 遵循 W3C 标准
    GCanvas 提供了一套类似于 H5 Canvas 标准的 JavaScript API,开发人员基于这套 API 可以方便的去做图形绘制、动画渲染等。开发的体验与 H5 Canvas 是完全一样的。

  • 跨平台
    GCanvas 的内核基于 OpenGL ES, 用 C++ 实现了一套用于描述 Canvas 标准 API 的接口实现。我们将其称为渲染引擎内核。并通过交叉编译,使得可以适配 Android、iOS 这两大主流移动平台,因而具有跨平台的特性。

  • 高性能
    早期移动平台上 H5 Canvas 去做一些复杂的动画或游戏,在 WebView 上的体验非常差。 主要原因是 WebView 对 GPU 硬件加速的支持差。高性能则是充分利用了 GPU 硬件的渲染能力,主要体现两个方面:

    • 对于 Android 3.0 以前的系统,Android 的渲染管线是不支持硬件加速的,WebView 中的 Canvas 不能获得 GPU 的图形渲染能力的支持。对于这类系统,通过 GCanvas 可以获得更底层的 OpenGL ES 的硬件加速能力提高渲染效率。
    • 链路上来看,缩短了调用路径,提高了渲染性能。使用了 GCanvas 则不需要经过 WebView 内部的复杂逻辑处理和图层树渲染,而是让 JavaScript 通过桥接方式直接调用渲染引擎内核(OpenGL ES)。

GCanvas 组成

如上图所示 GCanvas 由三层组成 JavaScript 层、插件层、核心渲染库。

  • JavaScript 层
    JavaScript 提供对外统一的 API,支持 Canvas 2D 和 WebGL 的功能接口。接口支持情况请参考 API 覆盖

  • 插件层
    插件层核心包含三部分。

    • Bridge 桥接
      JavaScript 到 Native 的桥接,比较主流的方式 JSBridge 和 JSBinding。JSBridge 实现方式,如 Cordva、WebviewJavascriptBridge 等。 还可以用 JSBinding 方式来实现,如 V8、JavascriptCore 等。实际的应用场景中这两种桥接方式都有支持。

    • 通用插件
      通用插件包含了通用插件接口与实现、GCanvas 的管理、渲染命令队列管理、纹理缓存等。支持不同类型桥接方式下的扩展。

    • 系统适配
      系统适配涉及 Android 和 iOS 对 OpenGL ES 实现的差异,网络图片下载,字体渲染等方面。

  • 核心渲染库
    核心渲染库包括对外统一的接口,以及 Contex2D 和 WebGL 模块,底层则是对 OpenGL ES API 等分装。

GCanvas 流程

上图是 JavaScript 层渲染核心库的概要流程,关键的两个流程是初始化和渲染。

  • 初始化
    初始化,JavaSript 层获取配置判断运行环境,通过桥接层,插件层完成视图和 GCanvas 的创建。进一步完成对 OpenGL 环境的初始化。

  • 渲染
    渲染,JavaScript 层将所有的API调用托管,并且转换成自定义的命令格式(命令类型 + 参数的组合)。渲染触发则由 JavaScript 定时器触发或者手动触发的方式,将这些命令下发到渲染核心库执行。

以 Weex 为例, 绘制图形和图片的测试代码如下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<template>
<div ref="test">
<gcanvas ref="canvas_holder" style="width:750; height:750; background-color:rgba(0, 0, 0, 0.1)"></gcanvas>
</div>
</template>
<script>
var GCanvas=require('weex-gcanvas');
var Image=require('weex-gcanvas/gcanvasimage');

module.exports = {
mounted: function () {

//1、初始化 GCanvas
var ref = this.$refs.canvas_holder;
var gcanvas = GCanvas.start(ref);
var ctx = gcanvas.getContext('2d');

//2、执行渲染操作
//rect
ctx.fillStyle = 'red';
ctx.fillRect(0, 0, 100, 100);

//rect
ctx.fillStyle = 'black';
ctx.fillRect(100, 100, 100, 100);
ctx.fillRect(25, 210, 700, 5);

//circle
ctx.arc(450, 200, 100, 0, Math.PI * 2, true);
ctx.fill();

//drawImage
var image = new Image();
image.onload = function(){
ctx.drawImage(image, 100, 330);
ctx.drawImage(image, 100+300, 330, 225, 75);
}
image.src = 'https://www.khronos.org/assets/uploads/ceimg/made/assets/uploads/apis/OpenGL-ES_100px_May16_225_75.png';
}
};
</script>

通过 Weex Playground 运行结果如下

具体分析下整个流程。结合插件层和核心渲染库来分析。

  • 插件层流程
    以 iOS 为例分析,Android 的过程是类似的。

    • GLKView 视图创建,并且与 GCanvas 对象建立绑定关系;
    • GCVCommon,资源加载与纹理绑定;
    • GCanvasPlugin,设置位置信息、设备比率、下发渲染命令;
  • 渲染库流程

渲染命令的解析,最终通过调用 OpenGL ES 的方法或组合方法来实现 Context2D 和 WebGL 的效果,生成帧缓存,提交给 GPU 渲染,最后在绑定的 GLKView 视图上显示。

  • Context2D,需要实现诸如 GPath、GTexture、GTransform、GTriangulate 等来实现 Canvas 的渲染效果;
  • WebGL 相对简单,WebGL1.0 的 API 基本都能与从 OpenGL ES2.0 找到与之相对应的 API;

GCanvas 测试例子

下面给出一些 GCanvas 的案例。

  • GCanvas 与 H5 Canvas 性能对比


    Android 平台,左边是 GCanvas,右边是 H5 Canvas。同屏渲染图片越多,性能差异越明显。

  • Hilo 2D
    100 条鱼

    基于 Hilo 2D 动画库,满屏鱼的动画测试。

  • Chart 图标渲染
    Chart 图标库的渲染效果

    基于图表库,不同类型的图表渲染测试。

附:GCanvas API 支持情况

最后附上 GCanvas Contex2D 和 WebGLAPI 的支持列表,支持常用的接口。另外,WebGL 的 API 目前正在做补全开发,后续会支持 WebGL1.0 API 的全覆盖。

  • Context2D API
API名称 API类型 状态
fillStyle Attribute getter/setter Implemented
strokeStyle Attribute getter/setter Empty
shadowColor Attribute getter/setter Empty
shadowBlur Attribute getter/setter Empty
shadowOffsetX Attribute getter/setter Empty
shadowOffsetY Attribute getter/setter Empty
createLinearGradient() Method Empty
createPattern() Method Empty
createRadialGradient() Method Empty
addColorStop() Method Empty
isPointInPath() Method Empty
createEvent() Method Empty
toDataURL() Method Empty
lineCap Attribute getter/setter Implemented
lineJoin Attribute getter/setter Implemented
lineWidth Attribute getter/setter Implemented
miterLimit Attribute getter/setter Implemented
font Attribute getter/setter Implemented
textAlign Attribute getter/setter Implemented
textBaseline Attribute getter/setter Implemented
globalAlpha Attribute getter/setter Implemented
globalCompositeOperation Attribute getter/setter Implemented
rect() Method Implemented
fillRect() Method Implemented
strokeRect() Method Implemented
clearRect() Method Implemented
fill() Method Implemented
stroke() Method Implemented
beginPath() Method Implemented
moveTo() Method Implemented
closePath() Method Implemented
lineTo() Method Implemented
clip() Method Implemented
quadraticCurveTo() Method Implemented
bezierCurveTo() Method Implemented
arc() Method Implemented
arcTo() Method Implemented
scale() Method Implemented
rotate() Method Implemented
translate() Method Implemented
transform() Method Implemented
setTransform() Method Implemented
fillText() Method Implemented
strokeText() Method Implemented
measureText() Method Implemented
drawImage() Method Implemented
createImageData() Method Implemented
getImageData() Method Implemented
putImageData() Method Implemented
save() Method Implemented
restore() Method Implemented
getContext() Method Implemented
loadTexture() Method Implemented
unloadTexture() Method Implemented
resetTransform() Method Implemented
render() Method Implemented
capture() Method Implemented
resetClip() Method Implemented
  • WebGL API
API名称 API类型 状态
viewport() Method Implemented
vertexAttribPointer() Method Implemented
vertexAttrib2fv() Method Implemented
useProgram() Method Implemented
uniformMatrix4fv() Method Implemented
uniformMatrix3fv() Method Implemented
uniformMatrix2fv() Method Implemented
uniform4iv() Method Implemented
uniform4i() Method Implemented
uniform4fv() Method Implemented
uniform4f() Method Implemented
uniform3iv() Method Implemented
uniform3i() Method Implemented
uniform3fv() Method Implemented
uniform3f() Method Implemented
uniform2iv() Method Implemented
uniform2i() Method Implemented
uniform2fv() Method Implemented
uniform2f() Method Implemented
uniform1iv() Method Implemented
uniform1i() Method Implemented
uniform1fv() Method Implemented
uniform1f() Method Implemented
texParameteri() Method Implemented
texImage2D() Method Implemented
shaderSource() Method Implemented
scissor() Method Implemented
renderbufferStorage() Method Implemented
pixelStorei() Method Implemented
linkProgram() Method Implemented
lineWidth() Method Implemented
getUniformLocation() Method Implemented
getShaderParameter() Method Implemented
getAttribLocation() Method Implemented
generateMipmap() Method Implemented
frontFace() Method Implemented
framebufferTexture2D() Method Implemented
flush() Method Implemented
enableVertexAttribArray() Method Implemented
enable() Method Implemented
drawElements() Method Implemented
disableVertexAttribArray() Method Implemented
disable() Method Implemented
depthMask() Method Implemented
depthFunc() Method Implemented
deleteTexture() Method Implemented
deleteShader() Method Implemented
deleteRenderbuffer() Method Implemented
deleteProgram() Method Implemented
deleteFramebuffer() Method Implemented
deleteBuffer() Method Implemented
cullFace() Method Implemented
createTexture() Method Implemented
createShader() Method Implemented
createRenderbuffer() Method Implemented
createProgram() Method Implemented
createFramebuffer() Method Implemented
createBuffer() Method Implemented
compileShader() Method Implemented
colorMask() Method Implemented
clearStencil() Method Implemented
clearDepth() Method Implemented
clearColor() Method Implemented
clear() Method Implemented
bufferData() Method Implemented
blendFuncSeparate() Method Implemented
blendFunc() Method Implemented
blendEquationSeparate() Method Implemented
blendEquation() Method Implemented
bindRenderbuffer() Method Implemented
bindFramebuffer() Method Implemented
bindBuffer() Method Implemented
bindAttribLocation() Method Implemented
attachShader() Method Implemented
activeTexture() Method Implemented
validateProgram() Method Empty
texSubImage2D() Method Empty
texParameterf() Method Empty
stencilOpSeparate() Method Empty
stencilOp() Method Empty
stencilMaskSeparate() Method Empty
stencilMask() Method Empty
stencilFuncSeparate() Method Empty
stencilFunc() Method Empty
sampleCoverage() Method Empty
readPixels() Method Empty
polygonOffset() Method Empty
isTexture() Method Empty
isShader() Method Empty
isRenderbuffer() Method Empty
isProgram() Method Empty
isFramebuffer() Method Empty
isEnabled() Method Empty
isContextLost() Method Empty
isBuffer() Method Empty
getVertexAttribOffset() Method Empty
getVertexAttrib() Method Empty
getUniform() Method Empty
getTexParameter() Method Empty
getSupportedExtensions() Method Empty
getShaderSource() Method Empty
getShaderPrecisionFormat() Method Empty
getShaderInfoLog() Method Empty
getRenderbufferParameter() Method Empty
getProgramParameter() Method Empty
getProgramInfoLog() Method Empty
getParameter() Method Empty
getFramebufferAttachmentParameter() Method Empty
getExtension() Method Empty
getError() Method Empty
getContextAttributes() Method Empty
getBufferParameter() Method Empty
getAttachedShaders() Method Empty
getActiveUniform() Method Empty
getActiveAttrib() Method Empty
drawArrays / drawArraysInstancedANGLE() Method Empty
detachShader() Method Empty
depthRange() Method Empty
copyTexSubImage2D() Method Empty
copyTexImage2D() Method Empty
compressedTexSubImage2D() Method Empty
compressedTexImage2D() Method Empty
checkFramebufferStatus() Method Empty
bufferSubData() Method Empty
blendColor() Method Empty
bindTexture() Method Undefined
commit() Method Undefined
finish() Method Undefined
framebufferRenderbuffer() Method Undefined
hint() Method Undefined

题图:https://unsplash.com/photos/y3KZwM_nBTQ By @Trevor Paterson