• 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



  • 相关阅读:
    基于Cat的分布式调用追踪
    python3.8.0 Django 开发后端接口api 部署到 Linux Centos7上
    openlayers上添加点击事件
    openlayers在底图上添加静态icon
    vue中使用kindeditor富文本编辑器2
    openlayers绘制点,线,圆等
    openLayers绘制静态底图
    快速调用Android虚拟机
    flutter环境配置window10
    reactjs中配置代理跨域
  • 原文地址:https://www.cnblogs.com/fanfeng/p/3219751.html
Copyright © 2020-2023  润新知