Android 从Android3.0(API Level 11)开始就支持了硬件加速,在target api >= 14会默认开启,利用GPU代替CPU绘制,软加速是利用Skia,而硬件加速是利用OpenGL绘制。缺点是增加了内存占用。
本文只是在java层去看硬件加速,没有深究jni层如何绘制。
-
RenderNode 每个View都有一个RenderNode与之对应
-
RenderThread jin层会创建一个对应的线程,loop循环接收RenderNode
-
DisplayList jin层将DisplayListCanvas的操作转化到DisplayList
-
DisplayListCanvas java层上canvas缓存所有绘制操作,设置到RenderNode中
基本流程:
- UI线程负责构建操作DisplayList
- RenderThread线程利用OpenGL去绘制DisplayList的操作
参考之前的文章《View/ViewGroup 绘制流程和疑惑(一)》 可以了解整个View/ViewGroup/ViewRootImpl整体的绘制流程。
硬件加速的绘制流程基本上是一致的,只不过在draw流程上有不同的分歧点。
我们知道,子View的invalidate标记dirty区域,借由着ViewParent的invalidateChildInParent(int[] location, Rect dirty),到顶层的DecorView,最后触发了ViewRootImpl的invalidateChildInParent(),引起schedualTraversals()。
在文章《Android 屏幕刷新机制》讲过Vsync信号到来的时候,才会引起ViewRootImpl的preformTraversals()流程到draw()。
ThreadedRender初始化
在添加窗口WindowManagerGlobal.addView()会调用ViewRootlImpl的setView()
// WindowManagerGlobal
public void addView(View view, ViewGroup.LayoutParams params,
Display display, Window parentWindow) {
root.setView(view, wparams, panelParentView);
}
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
if (mSurfaceHolder == null) {
enableHardwareAcceleration(attrs);
}
}
private void enableHardwareAcceleration(WindowManager.LayoutParams attrs) {
mAttachInfo.mHardwareAccelerated = false;
mAttachInfo.mHardwareAccelerationRequested = false;
// 根据标记位,判断是否要硬件加速
final boolean hardwareAccelerated =
(attrs.flags & WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED) != 0;
if (hardwareAccelerated) {
// 是否支持硬件加速:判断是否支持OpenGL
if (!ThreadedRenderer.isAvailable()) {
return;
}
if (!ThreadedRenderer.sRendererDisabled
|| (ThreadedRenderer.sSystemRendererDisabled && forceHwAccelerated)) {
if (mAttachInfo.mThreadedRenderer != null) {
mAttachInfo.mThreadedRenderer.destroy();
}
// 创建ThreadedRender
mAttachInfo.mThreadedRenderer = ThreadedRenderer.create(mContext, translucent,
attrs.getTitle().toString());
}
}
}
public static ThreadedRenderer create(Context context, boolean translucent, String name) {
ThreadedRenderer renderer = null;
if (isAvailable()) {
renderer = new ThreadedRenderer(context, translucent, name);
}
return renderer;
}
ThreadedRenderer(Context context, boolean translucent, String name) {
// jni 创建 RenderNode
long rootNodePtr = nCreateRootRenderNode();
// 赋值给根布局的RenderNode
mRootNode = RenderNode.adopt(rootNodePtr);
// 创建ThreadProxy用来向RenderThread线程提交操作
mNativeProxy = nCreateProxy(translucent, rootNodePtr);
}
View的RenderNode初始化
// View.java
public View(Context context) {
mRenderNode = RenderNode.create(getClass().getName(), this);
}
public static RenderNode create(String name, @Nullable View owningView) {
return new RenderNode(name, owningView);
}
private RenderNode(String name, View owningView) {
mNativeRenderNode = nCreate(name);
NoImagePreloadHolder.sRegistry.registerNativeAllocation(this, mNativeRenderNode);
mOwningView = owningView;
}
Draw() 流程
private void draw(boolean fullRedrawNeeded) {
Surface surface = mSurface;
final Rect dirty = mDirty;
if (!dirty.isEmpty() || mIsAnimating || accessibilityFocusDirty) {
// 硬件加速
if (mAttachInfo.mThreadedRenderer != null && mAttachInfo.mThreadedRenderer.isEnabled()) {
boolean invalidateRoot = accessibilityFocusDirty || mInvalidateRootRequested;
mInvalidateRootRequested = false;
if (invalidateRoot) {
mAttachInfo.mThreadedRenderer.invalidateRoot();
}
mAttachInfo.mThreadedRenderer.draw(mView, mAttachInfo, this);
} else {
// 软件加速
if (!drawSoftware(surface, mAttachInfo, xOffset, yOffset, scalingRequired, dirty)) {
return;
}
}
}
硬件加速:mAttachInfo.mThreadedRenderer.draw(mView, mAttachInfo, this)
软件加速:drawSoftware(surface, mAttachInfo, xOffset, yOffset, scalingRequired, dirty)
// ThreadedRender
// view指向的DecorView
void draw(View view, AttachInfo attachInfo, DrawCallbacks callbacks) {
attachInfo.mIgnoreDirtyState = true;
final Choreographer choreographer = attachInfo.mViewRootImpl.mChoreographer;
choreographer.mFrameInfo.markDrawStart();
updateRootDisplayList(view, callbacks);
…
int syncResult = nSyncAndDrawFrame(mNativeProxy, frameInfo, frameInfo.length);
}
// 更新所有RenderNode 创建DisplayListCanvas赋值到RenderNode
private void updateRootDisplayList(View view, DrawCallbacks callbacks) {
updateViewTreeDisplayList(view);
if (mRootNodeNeedsUpdate || !mRootNode.isValid()) {
DisplayListCanvas canvas = mRootNode.start(mSurfaceWidth, mSurfaceHeight);
try {
final int saveCount = canvas.save();
canvas.translate(mInsetLeft, mInsetTop);
callbacks.onPreDraw(canvas);
canvas.insertReorderBarrier();
canvas.drawRenderNode(view.updateDisplayListIfDirty());
canvas.insertInorderBarrier();
callbacks.onPostDraw(canvas);
canvas.restoreToCount(saveCount);
mRootNodeNeedsUpdate = false;
} finally {
mRootNode.end(canvas);
}
}
}
//
private void updateViewTreeDisplayList(View view) {
...
view.updateDisplayListIfDirty();
}
RenderedThread从DecorView开始,往所有的ViewGroup/View更新RenderNode
// View.java
public RenderNode updateDisplayListIfDirty() {
final RenderNode renderNode = mRenderNode;
final DisplayListCanvas canvas = renderNode.start(width, height);
canvas.setHighContrastText(mAttachInfo.mHighContrastText);
try {
if (layerType == LAYER_TYPE_SOFTWARE) {
buildDrawingCache(true);
Bitmap cache = getDrawingCache(true);
if (cache != null) {
canvas.drawBitmap(cache, 0, 0, mLayerPaint);
}
} else {
// 如果是ViewGroup,自身不用绘制,直接递归子View
if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
dispatchDraw(canvas);
} else {
draw(canvas);
}
}
} finally {
renderNode.end(canvas);
setDisplayListProperties(renderNode);
}
return renderNode;
}
public void end(DisplayListCanvas canvas) {
long displayList = canvas.finishRecording();
nSetDisplayList(mNativeRenderNode, displayList);
canvas.recycle();
}
从RenderNode获取DisplayListCanvas,将所有操作写入到DisplayListCanvas,最后交给RenderNode,完成构建DisplayList。最后调用nSyncAndDrawFrame
参考:
https://www.jianshu.com/p/7bf306c09c7e
https://www.jb51.net/article/143618.htm
原创文章,作者:奋斗,如若转载,请注明出处:https://blog.ytso.com/6241.html