之前讨论过skia codec部分在o,p上的变化,比如增加了heif解码等。
其实skia在android o,p的变化不只这些。
印象最深刻的还是渲染部分
从o开始hwui渲染支持skia opengl,原来hwui只支持opengl渲染,只不过在o里,skia opengl是可选的方式,默认还是opengl,但在p上已经默认采用skia opengl了,而且去掉了选择。
Android o上的选项
Android O上相关的代码
/**
* Defines the rendering pipeline to be used by the ThreadedRenderer.
*
* Possible values:
* "opengl", will use the existing OpenGL renderer
* "skiagl", will use Skia's OpenGL renderer
* "skiavk", will use Skia's Vulkan renderer
*
* @hide
*/
public static final String DEBUG_RENDERER_PROPERTY = "debug.hwui.renderer";
上边定义了可选的几个选项,是不是看到了vulkan,看来android早有打算
Readback& RenderThread::readback() {
if (!mReadback) {
auto renderType = Properties::getRenderPipelineType();
switch (renderType) {
case RenderPipelineType::OpenGL:
mReadback = new OpenGLReadbackImpl(*this);
break;
case RenderPipelineType::SkiaGL:
case RenderPipelineType::SkiaVulkan:
// It works to use the OpenGL pipeline for Vulkan but this is not
// ideal as it causes us to create an OpenGL context in addition
// to the Vulkan one.
mReadback = new skiapipeline::SkiaOpenGLReadback(*this);
break;
default:
LOG_ALWAYS_FATAL("canvas context type %d not supported", (int32_t) renderType);
break;
}
}
return *mReadback;
}
同样看到了vulkan,以及相关代码,但是并没有启动,应该还没有实现好
Android P上的代码
Readback& RenderThread::readback() {
if (!mReadback) {
auto renderType = Properties::getRenderPipelineType();
switch (renderType) {
case RenderPipelineType::OpenGL:
mReadback = new OpenGLReadbackImpl(*this);
break;
case RenderPipelineType::SkiaGL:
mReadback = new skiapipeline::SkiaOpenGLReadback(*this);
break;
case RenderPipelineType::SkiaVulkan:
mReadback = new skiapipeline::SkiaVulkanReadback(*this);
break;
default:
LOG_ALWAYS_FATAL("canvas context type %d not supported", (int32_t)renderType);
break;
}
}
return *mReadback;
}
看上去p上hwui已经开始支持vulkan了
class SkiaVulkanReadback : public Readback {
public:
SkiaVulkanReadback(renderthread::RenderThread& thread) : Readback(thread) {}
virtual CopyResult copySurfaceInto(Surface& surface, const Rect& srcRect,
SkBitmap* bitmap) override {
//TODO: implement Vulkan readback.
return CopyResult::UnknownError;
}
virtual CopyResult copyGraphicBufferInto(GraphicBuffer* graphicBuffer,
SkBitmap* bitmap) override {
//TODO: implement Vulkan readback.
return CopyResult::UnknownError;
}
但看代码实际上还是未启用状态可能有很多问题还没解决
RenderPipelineType Properties::getRenderPipelineType() {
if (sRenderPipelineType != RenderPipelineType::NotInitialized) {
return sRenderPipelineType;
}
char prop[PROPERTY_VALUE_MAX];
property_get(PROPERTY_RENDERER, prop, "skiagl");
if (!strcmp(prop, "skiagl")) {
ALOGD("Skia GL Pipeline");
sRenderPipelineType = RenderPipelineType::SkiaGL;
} else if (!strcmp(prop, "skiavk")) {
ALOGD("Skia Vulkan Pipeline");
sRenderPipelineType = RenderPipelineType::SkiaVulkan;
} else { //"opengl"
ALOGD("HWUI GL Pipeline");
sRenderPipelineType = RenderPipelineType::OpenGL;
}
return sRenderPipelineType;
Android p上默认已经是skiagl了,而且skiavk已经ready或者至少可以work了
效率问题
skia opengl会比opengl快吗?
网上很多人都表示skia opengl比opengl快,但是从实现的角度上讲核心没有不同,不同的可能是模块代码结构流程,并没有实质的提升,更不会出现能从使用者的角度观察到变化。因此做了一个实验,在60fps的一个场景下对opengl和skia opengl的gl绘制耗时做了一个对比。
OpenGL
OpenGL skia
draw: display list绘制信息
prepare: 同步时间
Process: gl绘制时间
Execute: swapbuffer时间
从上边的数据可以看到两种方式process的时间基本没有差别,而且整体渲染的时间也不相上下。所以从实验角度也不存在谁比谁更快。
而且两个cpu使用情况也基本相同。没什么差别。
真正的提升应该是在vulkan实现之后
这是官方的数据,有必要去了解下android vulkan以及skia vulkan。
Allows to set rendering pipeline mode to OpenGL (default), Skia OpenGL
or Vulkan.
*/
//#define PROPERTY_RENDERER “debug.hwui.renderer"
在android p上可以通过设置上边的属性为skiavk来指定vulkan,但是在o上不要这么做,因为在o上vulkan还没有真正实现,会有很多问题比如应用打不开等等。
下边是在android p上同一场景的一组数据对比,看数据总体上skia vulkan比skia opengl有很比较大的提升,但是又一些很大的凸起,不太稳定,没有skia opengl平稳,可能还没优化好,也许要等到adnroid 9.2或者android Q才能正式发布。
skia OpenGL
skia vulkan
android 2DUI的渲染发展大概是这么一个进化过程
Android早期通过skia库进行2d渲染,后来加入了hwui利用opengl替换skia进行大部分渲染工作,现在开始用skia opengl替换掉之前的opengl,从p的代码结构上也可以看出,p开始skia库不再作为一个单独的动态库so,而是静态库a编译到hwui的动态库里,将skia整合进hwui,hwui调用skia opengl,也为以后hwui使用skia vulkan做铺垫。