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




免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM