您的位置:首页 > 移动开发 > Android开发

Android系统--视图绘制 (View Render)

2013-11-21 16:29 330 查看

1. 简介

Android系统--视图绘制主要由以下几部分组成:

1) Canvas(画布)

提供画图所需要的所有工具,即各种draw函数;当前可用的画布对象有:具有硬件加速的GLES20Canvas和GLES20RecordingCanvas,不使用硬件加速的CompatibleCanvas)。

2) View(视图)

在具体画布对象上完成各种绘制图形的操作,可根据需要选择以上三种画布中的一种。

3) Gl20Renderer(把图直接绘制到屏幕上)

它是硬件加速视图绘制的引擎,负责整个与硬件加速相关的视图绘制过程,具体功能如下:

(1) 创建以下实例对象:

• GLES20Canvas (Canvas)

• GLES20DisplayList (DisplayList)

• GLES20TextureLayer (HardwareLayer)

• GLES20RenderLayer (HardwareLayer)

• SurfaceTexture

• Gl20Renderer (HardwareRenderer)

(2) 在GlRenderer.draw中调用View.getDisplayList()完成DisplayList命令的录制,并返回DisplayList

注:只有View被attach到硬件加速,才能创建DisplayList;

真正的命令录制工作在View.getDisplayList(DisplayList displayList, boolean isLayer)中完成。

(3) 在GlRenderer.draw中调用GLES20Canvas.drawDisplayList,把DisplayList中录制的命令回放在画布上。

(4) Gl20Renderer对象对应的画布为GLES20Canvas,Gl20Renderer对象在画布上的绘制实际上是绘制在OPENGL绘制上下文对应的主缓冲区。

4) GLES20DisplayList(把录制命令录制到Native的DiplayList中)

GLES20DisplayList对象创建具体的DisplayList对象及绘制用的画布(GLES20RecordingCanvas画布),完成视图绘制操作的DisplayList命令录制等工作。

5) GLES20RenderLayer(绘制到FOB Layer中,当作纹理)

负责创建硬件Layer层(GLES20Canvas.nCreateLayer)和绘制用到的画布(GLES20Canvas,使用Layer实例化GLES20Canvas(layer, trans))等工作。

为了有效支持视图的多层绘制,视图对象可以创建一个HardwareLayer层完成视图的图形在硬件纹理上的绘制操作或者其它特效操作,这就是GLES20RenderLayer对象的作用,创建独立的层并返回相应的画布供视图绘制使用。

1.1 View.draw(Canvas canvas)六步曲

此函数将把View自身及其所有的子子孙孙绘制到给定的画布上。其画图过程主要分为以下六步:

1) 画背景

2) 如果需要,保存画布的层为未来的淡入淡出做好准备

3) 画View本身的内容

4) 画它的孩子

5) 如果需要,画淡入淡出的边缘并恢复层

6) 画装饰部分(如:滚动条)

/**
* Manually render this view (and all of its children) to the given Canvas.
* The view must have already done a full layout before this function is
* called.  When implementing a view, implement
* {@link #onDraw(android.graphics.Canvas)} instead of overriding this method.
* If you do need to override this method, call the superclass version.
*
* @param canvas The Canvas to which the View is rendered.
*/
public void draw(Canvas canvas) {
final int privateFlags = mPrivateFlags;
final boolean dirtyOpaque = (privateFlags & PFLAG_DIRTY_MASK) == PFLAG_DIRTY_OPAQUE &&
(mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState);
mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;

/*
* Draw traversal performs several drawing steps which must be executed
* in the appropriate order:
*
*      1. Draw the background
*      2. If necessary, save the canvas' layers to prepare for fading
*      3. Draw view's content
*      4. Draw children
*      5. If necessary, draw the fading edges and restore layers
*      6. Draw decorations (scrollbars for instance)
*/

// Step 1, draw the background, if needed
int saveCount;

if (!dirtyOpaque) {
final Drawable background = mBackground;
if (background != null) {
final int scrollX = mScrollX;
final int scrollY = mScrollY;

if (mBackgroundSizeChanged) {
background.setBounds(0, 0,  mRight - mLeft, mBottom - mTop);
mBackgroundSizeChanged = false;
}

if ((scrollX | scrollY) == 0) {
background.draw(canvas);
} else {
canvas.translate(scrollX, scrollY);
background.draw(canvas);
canvas.translate(-scrollX, -scrollY);
}
}
}

// skip step 2 & 5 if possible (common case)
final int viewFlags = mViewFlags;
boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;
if (!verticalEdges && !horizontalEdges) {
// Step 3, draw the content
if (!dirtyOpaque) onDraw(canvas);

// Step 4, draw the children
dispatchDraw(canvas);

// Step 6, draw decorations (scrollbars)
onDrawScrollBars(canvas);

// we're done...
return;
}
}


2. 家族图谱

2.1 View家族图谱



2.2 Canvas和HardwareRenderer家族图谱



2.3 DisplayList和HardwareLayer家族图谱



2.4 Native OpenGLRenderer家族图谱



DisplayList.replay调用流程如下:

//Java
GlRenderer.draw((View view, View.AttachInfo attachInfo,...)
GLES20Canvas.drawDisplayList(DisplayList displayList, Rect dirty, int flags)->
//JNI
nDrawDisplayList->
android_view_GLES20Canvas_drawDisplayList(...,OpenGLRenderer* renderer,
DisplayList* displayList,...)->
//Native
OpenGLRenderer.drawDisplayList(DisplayList* displayList,...)->
DisplayList::replay(OpenGLRenderer& renderer,...)


2.5 Activity与Window家族图谱



• WindowManagerImpl:

允许把View子类增加到高级Window,应用不应该使用它,而是使用更高级的android.app.Activity或android.app.Dialog。

• PhoneWindow.mDecor(DecorView):窗口最高级的装饰View,即窗口的View树的树根,它包含:标准的Window框架、装饰、和放于窗口中的内容,可把它当作一个Window增加到Window Manager。

2.6 Activity与PhoneWindow的关系

每一个Activity都有一个关联的PhoneWindow对象,用来描述一个应用程序的窗口。每一个应用程序窗口(PhoneWindow)内部又包含有一个装饰View对象(mDecor:DecorView,View树的树根)和一个内容View对象(mContentParent: ViewGroup),用来描述应用程序窗口的视图。

1) mContentParent(ViewGroup):是Layout 资源描述的视图树的树根,它是mDecor的孩子

2) mDecor(DecorView):是PhoneWindow窗口中的视图树的树根



2.7 Activity实例化PhoneWindow流程

Activity在attach函数中实例化了PhoneWindow和WindowManagerImpl,以供后面绘制视图使用。

Activity.attach(Context context, ActivityThread aThread,
Instrumentation instr, IBinder token, int ident,
Application application, Intent intent, ActivityInfo info,
CharSequence title, Activity parent, String id,
NonConfigurationInstances lastNonConfigurationInstances,
Configuration config)->
1) PolicyManager.makeNewWindow(Context context)
// 返回PhoneWindow实例并保存在mWindow中
{
Policy.makeNewWindow(Context context)->
//new PhoneWindow(context)
PhoneWindow(Context context)
//获取LayoutInflater,它可以把Layout XML实例化为对应的View Objects
}
2) Window.setWindowManager(
(WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
mToken, mComponent.flattenToString(),
(info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0)->
{
WindowManagerImpl.createLocalWindowManager(Window parentWindow)
// 返回WindowManagerImpl实例,并保存在Window.mWindowManager
}
3)mWindow.setContainer(mParent.getWindow())
4)mWindowManager = mWindow.getWindowManager()
//返回Window.mWindowManager
//即Activity与Window中的mWindowManager为同一个
//WindowManagerImpl实例


2.8 放置窗口内容setContentView

setContentView的功能是:把Layout XML资源文件实例化为一棵视图树,然后把它加入PhoneWindow.mContentParent中,即成为PhoneWindow.mContentParent的子女。

Activity.setContentView(int layoutResID)->
//设置Activity内容
PhoneWindow.setContentView(int layoutResID)->
LayoutInflater.inflate(layoutResID, mContentParent)->
//把XML资源文件实例化为一棵视图树,并返回视图树的树根(root)
//树根为ViewGroup实例
LayoutInflater.inflate(layoutResID, root, root != null)->
//根据资源生成XmlResourceParser
LayoutInflater.inflate(XmlPullParser parser, ViewGroup root, boolean attachToRoot)->
ViewGroup.addView(View child, LayoutParams params)->
{
//把资源文件中的视图树加入PhoneWindow中的mContentParent中
View.requestLayout()
View.invalidate(true)->
addViewInner(child, index, params, false)
//它将调用child.requestLayout(),依次递归下去
}
ViewGroup.invalidateChild(View child, final Rect dirty)->
ViewGroup.invalidateChildInParent(final int[] location, final Rect dirty)
//更新dirty区域


3. FBO (Frame Buffer Object)和RBO (Render Buffer Object)

在了解下面的内容之前,需要了解一下FBO和RBO,除了使用窗口系统固有的Frame Buffer外,可以创建Frame Buffer Object,用于off-screen rendering(离线渲染:就是通过OpenGL将绘制结果渲染到显存中的一张图片上,通过gl接口函数可以从显存读取到内存中)。FBO是一种特殊的Buffer Object。

3.1 FBO

1) glGenFramebuffers: 生成FBO对象的名字

2) glBindFramebuffer: 绑定FBO并进行实始化

3) glDeleteFramebuffers: 删除FBO对象

FBO创建后,还不能绘图,必须为FBO提供绘图的目标buffer,也即Render Buffer Object。

3.2 RBO

Render Buffer Object包含具体的图像数据:

1) glGenRenderbuffers:生成对象的名字

2) glBindRenderbuffer: 绑定名字到RenderBuffer

3) glRenderbufferStorage: 为render
buffer分配存储空间

3.3 把RBO连接到FBO上

glFramebufferRenderbuffer(GLenum target, GLenum attachment,GLenum renderbuffertarget, GLuint renderbuffer);

1) target:GL_DRAW_FRAMEBUFFER: 指定写入用途FBO

GL_READ_FRAMEBUFFER:指定读取用途FBO

GL_FRAMEBUFFER:指定两者

2) attachment:GL_COLOR_ATTACHMENT

GL_DEPTH_ATTACHMENT

GL_STENCIL_ATTACHMENT

GL_DEPTH_STENCIL_ATTACHMENT

3)renderbuffertarget: GL_RENDERBUFFER

4) renderbuffer: RBO名字

使用FBO可以创建出动态的texture,glFramebufferTexture可以绑定texture到FBO。

4. 各种各样的画布

从上面的家族图谱中可以看到,可用的画布有以下几种:

1) GLES20RecordingCanvas: 此GL画布用于录制画图操作

2) GLES20Canvas: 在OpenGL ES 2.0之上实现的画布

3) HardwareCanvas: 硬件加速的画布

3) Canvas: 实现画图操作的画布

4.1 Gl20Renderer使用的画布(直接绘制在屏幕上)

其相关代码如下:

Gl20Renderer.createCanvas()->

GLES20Canvas.GLES20Canvas(false, boolean translucent)->

nCreateRenderer()

/**
* Hardware renderer using OpenGL ES 2.0.
*/
static class Gl20Renderer extends GlRenderer {
private GLES20Canvas mGlCanvas;
final boolean mTranslucent;
//...
@Override
HardwareCanvas createCanvas() {
//创建直接绘制到屏幕上的画布,而不会录制到DisplayList中
return mGlCanvas = new GLES20Canvas(mTranslucent);
}
//...
}

/**
* An implementation of Canvas on top of OpenGL ES 2.0.
*/
class GLES20Canvas extends HardwareCanvas {

private final boolean mOpaque;
private int mRenderer;

//...
/**
* Creates a canvas to render directly on screen.
* 创建直接绘制到屏幕上的画布,而不会录制到DisplayList中
* 由Gl20Renderer.createCanvas调用
*/
GLES20Canvas(boolean translucent) {
// 直接调用OpenGL函数把图画到屏幕上
this(false, translucent);
}

/**
* Creates a canvas to render into an FBO.
* 创建离线绘制到FBO的画布
*/
GLES20Canvas(int layer, boolean translucent) {
mOpaque = !translucent;
// mRenderer为Native中LayerRenderer类的实例
mRenderer = nCreateLayerRenderer(layer);
setupFinalizer();
}

protected GLES20Canvas(boolean record, boolean translucent) {
mOpaque = !translucent;

if (record) {
// 把画图命令录制到DisplayListRenderer.mWriter中
// mRender为Native中DisplayListRenderer类的实例
mRenderer = nCreateDisplayListRenderer();
} else {
// 直接调用OpenGL函数把图画到屏幕上
// mRenderer为Native中OpenGLRenderer类的实例
mRenderer = nCreateRenderer();
}

setupFinalizer();
}
//...
}


4.2 GLES20RenderLayer使用的画布(离线绘制到FBO Layer)

GLES20RenderLayer.GLES20RenderLayer(w,h,trans)->

GLES20Canvas.nCreateLayer(w,h,trans,layerInfo)

GLES20Canvas.GLES20Canvas(int layer, boolean translucent)->

nCreateLayerRenderer(layer)

/**
* An OpenGL ES 2.0 implementation of {@link HardwareLayer}. This
* implementation can be used a rendering target. It generates a
* {@link Canvas} that can be used to render into an FBO using OpenGL.
*/
class GLES20RenderLayer extends GLES20Layer {
private int mLayerWidth;
private int mLayerHeight;

private final GLES20Canvas mCanvas;

GLES20RenderLayer(int width, int height, boolean isOpaque) {
super(width, height, isOpaque);

int[] layerInfo = new int[2];
// 请求Native LayerRenderer创建一个FBO Layer,以用于离线Render
mLayer = GLES20Canvas.nCreateLayer(width, height, isOpaque, layerInfo);
if (mLayer != 0) {
mLayerWidth = layerInfo[0];
mLayerHeight = layerInfo[1];

// 使用FBO Layer创建一个Native LayerRenderer,然后实例化画布
mCanvas = new GLES20Canvas(mLayer, !isOpaque);
mFinalizer = new Finalizer(mLayer);
} else {
mCanvas = null;
mFinalizer = null;
}
}
//...
}

/**
* An implementation of Canvas on top of OpenGL ES 2.0.
*/
class GLES20Canvas extends HardwareCanvas {

private final boolean mOpaque;
private int mRenderer;

//...
/**
* Creates a canvas to render directly on screen.
* 创建直接绘制到屏幕上的画布,而不会录制到DisplayList中
* 由Gl20Renderer.createCanvas调用
*/
GLES20Canvas(boolean translucent) {
// 直接调用OpenGL函数把图画到屏幕上
this(false, translucent);
}

/**
* Creates a canvas to render into an FBO.
* 创建离线绘制到FBO的画布
*/
GLES20Canvas(int layer, boolean translucent) {
mOpaque = !translucent;
// mRenderer为Native中LayerRenderer类的实例
mRenderer = nCreateLayerRenderer(layer);
setupFinalizer();
}

protected GLES20Canvas(boolean record, boolean translucent) {
mOpaque = !translucent;

if (record) {
// 把画图命令录制到DisplayListRenderer.mWriter中
// mRender为Native中DisplayListRenderer类的实例
mRenderer = nCreateDisplayListRenderer();
} else {
// 直接调用OpenGL函数把图画到屏幕上
// mRenderer为Native中OpenGLRenderer类的实例
mRenderer = nCreateRenderer();
}

setupFinalizer();
}
//...
}


4.3 GLES20RecordingCanvas使用的画布 (绘制到DisplayList)

GLES20DisplayList.start->

GLES20RecordingCanvas.obtain(GLES20DisplayList displayList)-> (static)

GLES20RecordingCanvas.GLES20RecordingCanvas()->

GLES20Canvas(true /*record*/, true /*translucent*/)->

nCreateDisplayListRenderer()

/**
* An implementation of display list for OpenGL ES 2.0.
*/
class GLES20DisplayList extends DisplayList {
// These lists ensure that any Bitmaps and DisplayLists recorded by a DisplayList are kept
// alive as long as the DisplayList is alive.  The Bitmap and DisplayList lists
// are populated by the GLES20RecordingCanvas during appropriate drawing calls and are
// cleared at the start of a new drawing frame or when the view is detached from the window.
final ArrayList<Bitmap> mBitmaps = new ArrayList<Bitmap>(5);
final ArrayList<DisplayList> mChildDisplayLists = new ArrayList<DisplayList>();

private GLES20RecordingCanvas mCanvas;

// Used for debugging
private final String mName;

// The native display list will be destroyed when this object dies.
// DO NOT overwrite this reference once it is set.
private DisplayListFinalizer mFinalizer;

GLES20DisplayList(String name) {
mName = name;
}

@Override
public HardwareCanvas start() {
if (mCanvas != null) {
throw new IllegalStateException("Recording has already started");
}

mValid = false;
// 使用GLES20DisplayList创建GLES20RecordingCanvas
mCanvas = GLES20RecordingCanvas.obtain(this);
mCanvas.start();
return mCanvas;
}
//...
}

/**
* An implementation of a GL canvas that records drawing operations.
* This is intended for use with a DisplayList. This class keeps a list of all the Paint and
* Bitmap objects that it draws, preventing the backing memory of Bitmaps from being freed while
* the DisplayList is still holding a native reference to the memory.
*/
class GLES20RecordingCanvas extends GLES20Canvas implements Poolable<GLES20RecordingCanvas> {
// The recording canvas pool should be large enough to handle a deeply nested
// view hierarchy because display lists are generated recursively.
private static final int POOL_LIMIT = 25;

private static final Pool<GLES20RecordingCanvas> sPool = Pools.synchronizedPool(
Pools.finitePool(new PoolableManager<GLES20RecordingCanvas>() {
public GLES20RecordingCanvas newInstance() {
return new GLES20RecordingCanvas();
}
@Override
public void onAcquired(GLES20RecordingCanvas element) {
}
@Override
public void onReleased(GLES20RecordingCanvas element) {
}
}, POOL_LIMIT));

private GLES20DisplayList mDisplayList;

private GLES20RecordingCanvas() {
//实例化DisplayListRender
super(true /*record*/, true /*translucent*/);
}

static GLES20RecordingCanvas obtain(GLES20DisplayList displayList) {
GLES20RecordingCanvas canvas = sPool.acquire();
canvas.mDisplayList = displayList;
return canvas;
}
// ...
}
/**
* An implementation of Canvas on top of OpenGL ES 2.0.
*/
class GLES20Canvas extends HardwareCanvas {

private final boolean mOpaque;
private int mRenderer;

//...
/**
* Creates a canvas to render directly on screen.
* 创建直接绘制到屏幕上的画布,而不会录制到DisplayList中
* 由Gl20Renderer.createCanvas调用
*/
GLES20Canvas(boolean translucent) {
// 直接调用OpenGL函数把图画到屏幕上
this(false, translucent);
}

/**
* Creates a canvas to render into an FBO.
* 创建离线绘制到FBO的画布
*/
GLES20Canvas(int layer, boolean translucent) {
mOpaque = !translucent;
// mRenderer为Native中LayerRenderer类的实例
mRenderer = nCreateLayerRenderer(layer);
setupFinalizer();
}

protected GLES20Canvas(boolean record, boolean translucent) {
mOpaque = !translucent;

if (record) {
// 把画图命令录制到DisplayListRenderer.mWriter中
// mRender为Native中DisplayListRenderer类的实例
mRenderer = nCreateDisplayListRenderer();
} else {
// 直接调用OpenGL函数把图画到屏幕上
// mRenderer为Native中OpenGLRenderer类的实例
mRenderer = nCreateRenderer();
}

setupFinalizer();
}
//...
}


5. 绘制(Render)元素小结

为了把图形绘制到屏幕上,必须使用Native Render,其最本质的东东是OpenGL,为了方便管理,其Native Render分为三类,其相关信息如下表所示:

Native Render类名

OpenGLRenderer

DisplayListRenderer

LayerRenderer

绘制到哪儿?

直接绘制到屏幕上

录制到SkWriter32

离线绘制到FBO Layer

JNI创建函数

nCreateRenderer

nCreateDisplayListRenderer

nCreateLayerRenderer

由谁管理?

GLES20Canvas

GLES20Canvas

GLES20Canvas

由谁使用?

Gl20Renderer

GLES20DisplayList

GLES20RenderLayer

使用者类别HardwareRenderer

DisplayList

HardwareLayer
画图五元素间的暧昧关系如下图所示:



6. 创建窗口(Window)流程

其基本流程如下所示:

ActivityThread.handleResumeActivity->
{
ActivityClientRecord.window = ActivityClientRecord.activity.getWindow();
View decor = ActivityClientRecord.window.getDecorView();
//实际调用PhoneWindow.getDecorView();
decor.setVisibility(View.INVISIBLE);

ViewManager wm = Activity.getWindowManager();
//wm是WindowManagerImpl实例
Activity.mDecor = decor;

WindowManager.LayoutParams l = r.window.getAttributes();
l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
l.softInputMode |= forwardBit;
if (a.mVisibleFromClient) {
a.mWindowAdded = true;
wm.addView(decor, l);--->
//即调用WindowManagerImpl.addView,
//把PhoneWindow.mDecor加入WindowManager中
}
}

WindowManagerImpl.addView(View view, ViewGroup.LayoutParams params)->
WindowManagerGlobal.addView(View view, ViewGroup.LayoutParams params,
Display display, Window parentWindow)->
(root = new ViewRootImpl(view.getContext(), display))
ViewRootImpl.setView(View view, WindowManager.LayoutParams attrs, View panelParentView)->
requestLayout()

mWindowSession.addToDisplay(mWindow,...) --> //to Window Manager Server

Session.addToDisplay(IWindow window, int seq, WindowManager.LayoutParams attrs,
int viewVisibility, int displayId, Rect outContentInsets,
InputChannel outInputChannel)->
WindowManagerService.addWindow(Session session, IWindow client, int seq,
WindowManager.LayoutParams attrs, int viewVisibility, int displayId,
Rect outContentInsets, InputChannel outInputChannel)->
new WindowState(WindowManagerService service, Session s, IWindow c, WindowToken token,
WindowState attachedWindow, int seq, WindowManager.LayoutParams a,
int viewVisibility, final DisplayContent displayContent)
// WindowState实例即为Window Manager中刚创建的窗口


在以上过程中,ViewRootImpl为客户端,通过IWindowSession接口把创建窗口的请求发送给Server端(Session),然后调用WindowManagerService中对应的功能函数。同时把IWindow.Stub (W extends IWindow.Stub)的实现实例发送给服务器端,以便WindowMangerService通过IWindow接口向ViewRootImpl发送命令。其相互关系如下图所示:



Activity<-->PhoneWindow<-->ViewRootImpl<-->WindowManagerService

在以上关系中,WindowManagerService系统中仅一个实例,其它三个实例一一对应,即一个Activity实例有一个唯一的PhoneWindow和ViewRootImpl实例与之一一对应。

7. 硬件绘制(Hardware Render)窗口流程

WMS.performLayoutAndPlaceSurfacesLocked->
WMS.performLayoutAndPlaceSurfacesLockedLoop->
WMS.performLayoutAndPlaceSurfacesLockedInner->
mRelayoutWhileAnimating.get(j).mClient.doneAnimating()->
//即IWindow.doneAnimating()

ViewRootImpl.W.doneAnimating()->
ViewRootImpl.dispatchDoneAnimating()->
ViewRootImpl.handleDispatchDoneAnimating()->
ViewRootImpl.scheduleTraversals()->
ViewRootImpl.mTraversalRunnable.run()->
ViewRootImpl.doTraversal()->
ViewRootImpl.performTraversals() ->
ViewRootImpl.performDraw()->
ViewRootImpl.draw()->
// ViewRootImpl.drawSoftware(..),软件render,暂且不讲,以下为硬件Render
attachInfo.mHardwareRenderer.draw(mView,...)->
// attachInfo.mHardwareRenderer实际为Gl20Renderer实例,
// 在enableHardwareAcceleration中实例化
// Gl20Renderer.createDisplayList: 实例化GLES20DisplayList
// Gl20Renderer.createHardwareLayer(w,h):实例化GLES20RenderLayer
// Gl20Renderer.create:实例化Gl20Renderer

GlRenderer.draw(View view, View.AttachInfo attachInfo,...)->
// 其mCanvas为GLES20Canvas,其对应的Native Render为OpenGLRenderer
GLES20Canvas.onPreDraw(dirty)
View.getDisplayList(mDisplayList, false)
// 如果mDisplayList为null, 则调用
mAttachInfo.mHardwareRenderer.createDisplayList
// 返回的DisplayList为GLES20DisplayList实例
GLES20DisplayList.start()
// 返回GLES20RecordingCanvas实例
//如果mLayerType为LAYER_TYPE_HARDWARE,则调用
mAttachInfo.mHardwareRenderer.createHardwareLayer(w,h,..)
//返回GLES20RenderLayer实例到mHardwareLayer中
GLES20RecordingCanvas.drawHardwareLayer(mHardwareLayer,...)

GLES20Canvas.drawDisplayList(displayList,...)
GLES20Canvas.onPostDraw()
EGL10.eglSwapBuffers(sEglDisplay, mEglSurface)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐