Profile GPU rendering

自Android 4.1引入了“Profile GPU rendering”这个开发工具以帮助分析应用程序性能并并精确定位渲染问题,Android 4.3增加了可视效果:On screen as bars/lines。模拟器中此功能生效要勾选AVD的:Emulation Options:User Host GPU。

这个选项的开关实现位于settings中DevelopmentSettings.java中的函数writeTrackFrameTimeOptions:

Code


其中HardwareRenderer.PROFILE_PROPERTY定义于HardwareRenderer.java

Code

抽象类GlRenderer中重写函数dumpGfxInfo:

Code

在“Profile GPU rendering”中勾选“In adb shell dumpsys gfxinfo”或者“adb shell setprop debug.hwui.profile true”之后,运行adb shell dumpsys gfxinfo package_name输出(ms):

com.android.deskclock/com.android.deskclock.DeskClock/android.view.ViewRootImpl@41770410
Draw    Process    Execute
31.73    10.66    11.73
29.34    6.74    8.19
74.70    31.81    26.01
5.96    4.51    5.67
59.04    3.42    6.61
19.34    5.00    7.14
33.70    18.27    138.73
2.97    14.80    14.26
4.28    3.27    15.31
2.25    3.83    4.03
3.18    1.87    3.89
3.09    1.92    5.38
14.55    3.01    16.52
2.66    3.74    3.83
5.69    1.97    72.48
4.27    1.93    12.90
0.73    4.84    4.49
36.66    6.62    7.53
12.80    3.22    17.49
6.31    4.86    4.73
4.55    3.42    4.46
1.95    1.91    13.81
15.05    23.02    5.10
21.86    1.86    4.61
4.87    8.40    5.24
4.49    6.78    4.21
7.15    30.36    3.70
12.38    24.17    4.89
2.77    5.27    22.00
3.26    5.66    4.02
1.74    3.98    22.07
2.23    3.30    4.34
0.86    2.89    13.56
1.00    13.85    13.94
0.84    1.34    13.86
3.45    2.42    3.81
0.69    1.48    14.75
0.64    1.32    13.88
0.46    1.41    14.48

其中:

Draw--Build display lists

Process—Process(Draw) display lists

Excute--Swap GL buffers

关于此数据分析详见Android Performance Case StudyAndroid application (performance and more) analysis tools - Tutorial。


重写了函数draw:

Code

1.buildDisplayList

Code

 view.getDisplayList()来自View.java

/**
     * <p>Returns a display list that can be used to draw this view again
     * without executing its draw method.</p>
     *
     * @return A DisplayList ready to replay, or null if caching is not enabled.
     *
     * @hide
     */
    public DisplayList getDisplayList() {
        mDisplayList = getDisplayList(mDisplayList, false);
        return mDisplayList;
    }

/**
     * Returns a DisplayList. If the incoming displayList is null, one will be created.
     * Otherwise, the same display list will be returned (after having been rendered into
     * along the way, depending on the invalidation state of the view).
     *
     * @param displayList The previous version of this displayList, could be null.
     * @param isLayer Whether the requester of the display list is a layer. If so,
     * the view will avoid creating a layer inside the resulting display list.
     * @return A new or reused DisplayList object.
     */
    private DisplayList getDisplayList(DisplayList displayList, boolean isLayer) {
        if (!canHaveDisplayList()) {
            return null;
        }

        if (((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 ||
                displayList == null || !displayList.isValid() ||
                (!isLayer && mRecreateDisplayList))) {
            // Don't need to recreate the display list, just need to tell our
            // children to restore/recreate theirs
            if (displayList != null && displayList.isValid() &&
                    !isLayer && !mRecreateDisplayList) {
                mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
                mPrivateFlags &= ~PFLAG_DIRTY_MASK;
                dispatchGetDisplayList();

                return displayList;
            }

            if (!isLayer) {
                // If we got here, we're recreating it. Mark it as such to ensure that
                // we copy in child display lists into ours in drawChild()
                mRecreateDisplayList = true;
            }
            if (displayList == null) {
                final String name = getClass().getSimpleName();
                displayList = mAttachInfo.mHardwareRenderer.createDisplayList(name);
                // If we're creating a new display list, make sure our parent gets invalidated
                // since they will need to recreate their display list to account for this
                // new child display list.
                invalidateParentCaches();
            }

            boolean caching = false;
            int width = mRight - mLeft;
            int height = mBottom - mTop;
            int layerType = getLayerType();

            final HardwareCanvas canvas = displayList.start(width, height);

            try {
                if (!isLayer && layerType != LAYER_TYPE_NONE) {
                    if (layerType == LAYER_TYPE_HARDWARE) {
                        final HardwareLayer layer = getHardwareLayer();
                        if (layer != null && layer.isValid()) {
                            canvas.drawHardwareLayer(layer, 0, 0, mLayerPaint);
                        } else {
                            canvas.saveLayer(0, 0, mRight - mLeft, mBottom - mTop, mLayerPaint,
                                    Canvas.HAS_ALPHA_LAYER_SAVE_FLAG |
                                            Canvas.CLIP_TO_LAYER_SAVE_FLAG);
                        }
                        caching = true;
                    } else {
                        buildDrawingCache(true);
                        Bitmap cache = getDrawingCache(true);
                        if (cache != null) {
                            canvas.drawBitmap(cache, 0, 0, mLayerPaint);
                            caching = true;
                        }
                    }
                } else {

                    computeScroll();

                    canvas.translate(-mScrollX, -mScrollY);
                    if (!isLayer) {
                        mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
                        mPrivateFlags &= ~PFLAG_DIRTY_MASK;
                    }

                    // Fast path for layouts with no backgrounds
                    if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
                        dispatchDraw(canvas);
                        if (mOverlay != null && !mOverlay.isEmpty()) {
                            mOverlay.getOverlayView().draw(canvas);
                        }
                    } else {
                        draw(canvas);
                    }
                }
            } finally {
                displayList.end();
                displayList.setCaching(caching);
                if (isLayer) {
                    displayList.setLeftTopRightBottom(0, 0, width, height);
                } else {
                    setDisplayListProperties(displayList);
                }
            }
        } else if (!isLayer) {
            mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
        }

        return displayList;
    }
View Code

2.drawDisplayList

Code

canvas.drawDisplayList来自HardwareCanvas.java,这是一个抽象接口:

Code

3.swapBuffers

Code

EGL10.java中的eglSwapBuffers->EGLImpl.java->com_google_android_gles_jni_EGLImpl.cpp

com_google_android_gles_jni_EGLImpl.cpp中:

Code



原文地址:https://www.cnblogs.com/fanfeng/p/3219751.html