OpenHarmony dump渲染和合成图层SurfaceBuffer指南

2023-11-18

      OpenHarmony dump渲染和合成图层SurfaceBuffer指南



引言

  博客停更很久了,提起笔来渐感生疏啊!看来,还是得抽出时间来更新更新啊!好了,感慨也发完了,是时候切入正题了。本篇博客主要以本人在实际项目的开发中,为了定位OpenHarmony显示异常究竟是GPU渲染,合成的问题,还是DC端送显异常的问题而来。这里为了后续的复盘,也为可能有共同需求的朋友所以记录下来,最终发展成为如何dump OpenHarmony渲染和合成图层SurfaceBuffer为png图片。(主要是教大家如何把锅甩给队友)!通过本篇博客,读者将会至少学会如下两点:

  • 通过dump OpenHarmony渲染图层SurfaceBuffer,查看OpenHarmony渲染结果是否正确
  • 通过dump OpenHarmony合成图层SurfaceBuffer,查看OpenHarmony合成结果是否正确

    这里需要注意一点的是,这里的合成指的是GPU(Client)的合成方式!

好了不多说了,直接开干!

能搜寻到这篇博客的,肯定是对OpenHarmony SurfaceBuffer有一定掌握的朋友,所以这里就不会过多解释一些名词和代码逻辑了。总之这是一篇专业性比较强的文章(因为一般的朋友也不会搜这个)!

注意:本篇的介绍是基于OpenHarmony 3.2 release平台为基础的,其中涉及的代码路径如下:

foundation/graphic/graphic_2d/rosen/modules/render_service/core/pipeline/rs_render_service_visitor.cpp
foundation/graphic/graphic_2d/rosen/modules/composer/hdi_backend/src/hdi_backend.cpp



一.自定义逻辑dump OpenHarmony渲染和合成图层SurfaceBuffer指南

由于此篇博客是实战类型的,所以也就不必对小伙伴们吆喝什么的了,这里没有九块九包邮,也没有九块九上车。有的只有是兄弟就砍一刀。


1.1 dump OpenHarmony渲染图层SurfaceBuffer

我们知道OpenHarmony中各个渲染图层是以RSSurfaceRenderNode存在的,所以我们只需要将RSSurfaceRenderNode对应的SurfaceBuffer保存成png图片即可。这里我们直接上我封装好的逻辑代码:

//头文件
#ifndef HDI_BACKEND_UTIL_H
#define HDI_BACKEND_UTIL_H


#include <vector>
#include <iostream>
#include <string>
#include "surface_buffer.h"
#include <unordered_map>
#include <refbase.h>
#include <parameter.h>
#include <parameters.h>
#include "pipeline/rs_surface_render_node.h"
namespace OHOS {
namespace Rosen {

using WriteToPngParam = struct {
    uint32_t width;
    uint32_t height;
    uint32_t stride;
    uint32_t bitDepth;
    const uint8_t *data;
};


class RSBaseRenderUtil {
public:
    static const int ALLSURFACES = 2;
    static bool WriteHdiOutToPng(const sptr<SurfaceBuffer> &buffer, const BufferHandle *bufferHandle);
    static bool WriteSurfaceBufferToPng(const sptr<SurfaceBuffer> &buffer);
    static bool WriteSurfaceRenderNodeToPng(const RSSurfaceRenderNode& node);

private:
    static bool WriteToPng(const std::string &filename, const WriteToPngParam &param);
    
};


} // namespace Rosen
} // namespace OHOS

#endif // HDI_BACKEND_UTIL_H





//具体实现
#include "hdi_backend_util.h"
#include "png.h"
#include "hdi_log.h"
#include <sys/time.h>


namespace OHOS {
namespace Rosen {

bool RSBaseRenderUtil::WriteToPng(const std::string &filename, const WriteToPngParam &param)
{
    HLOGI("RSBaseRenderUtil::WriteToPng filename = %s{public}", filename.c_str());
    png_structp pngStruct = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
    if (pngStruct == nullptr) {
        return false;
    }
    png_infop pngInfo = png_create_info_struct(pngStruct);
    if (pngInfo == nullptr) {
        png_destroy_write_struct(&pngStruct, nullptr);
        return false;
    }

    FILE *fp = fopen(filename.c_str(), "wb");
    if (fp == nullptr) {
        png_destroy_write_struct(&pngStruct, &pngInfo);
        return false;
    }
    png_init_io(pngStruct, fp);

    // set png header
    png_set_IHDR(pngStruct, pngInfo,
        param.width, param.height,
        param.bitDepth,
        PNG_COLOR_TYPE_RGBA,
        PNG_INTERLACE_NONE,
        PNG_COMPRESSION_TYPE_BASE,
        PNG_FILTER_TYPE_BASE);
    png_set_packing(pngStruct); // set packing info
    png_write_info(pngStruct, pngInfo); // write to header

    for (uint32_t i = 0; i < param.height; i++) {
        png_write_row(pngStruct, param.data + (i * param.stride));
    }
    png_write_end(pngStruct, pngInfo);

    // free
    png_destroy_write_struct(&pngStruct, &pngInfo);
    int ret = fclose(fp);
    return ret == 0;
}


bool RSBaseRenderUtil::WriteHdiOutToPng(const sptr<SurfaceBuffer> &buffer, const BufferHandle *bufferHandle)
{
    if((std::atoi((system::GetParameter("rosen.dump.surfacebuffer", "0")).c_str()) == ALLSURFACES) )
    {
        HLOGE("allow WriteHdiOutToPng");
        {
            if (bufferHandle == nullptr) {
                return false;
            }
            struct timeval now;
            gettimeofday(&now, nullptr);
            constexpr int secToUsec = 1000 * 1000;
            int64_t nowVal =  static_cast<int64_t>(now.tv_sec) * secToUsec + static_cast<int64_t>(now.tv_usec);
            std::string filename = "/data/hdioutput/hdi_output_layer_" +
                std::to_string(nowVal) + ".png";

            WriteToPngParam param;
            param.width = static_cast<uint32_t>(bufferHandle->width);
            param.height = static_cast<uint32_t>(bufferHandle->height);
            param.data = (uint8_t*)(buffer->GetVirAddr());
            param.stride = static_cast<uint32_t>(bufferHandle->stride);
            param.bitDepth = 8;
            
            WriteToPng(filename, param);
            
        }
    }
    return false;
}


bool RSBaseRenderUtil::WriteSurfaceBufferToPng(const sptr<SurfaceBuffer> &buffer)
{
    if((std::atoi((system::GetParameter("rosen.dump.surfacebuffer", "0")).c_str()) == ALLSURFACES) )
    {
        HLOGE("allow WriteHdiOutToPng");
        {
            BufferHandle *bufferHandle = buffer->GetBufferHandle();
            if (bufferHandle == nullptr) {
                return false;
            }
            struct timeval now;
            gettimeofday(&now, nullptr);
            constexpr int secToUsec = 1000 * 1000;
            int64_t nowVal =  static_cast<int64_t>(now.tv_sec) * secToUsec + static_cast<int64_t>(now.tv_usec);
            std::string filename = "/data/hdioutput/hdi_output_layer_" +
                std::to_string(nowVal) + ".png";

            WriteToPngParam param;
            param.width = static_cast<uint32_t>(bufferHandle->width);
            param.height = static_cast<uint32_t>(bufferHandle->height);
            param.data = (uint8_t*)(buffer->GetVirAddr());
            param.stride = static_cast<uint32_t>(bufferHandle->stride);
            param.bitDepth = 8;
            
            WriteToPng(filename, param);
            
        }
    }
    return false;
}


bool RSBaseRenderUtil::WriteSurfaceRenderNodeToPng(const RSSurfaceRenderNode& node)
{
    if((std::atoi((system::GetParameter("rosen.dump.rendernode", "0")).c_str()) == ALLSURFACES))
    {
        sptr<SurfaceBuffer> buffer = node.GetBuffer();
        if (buffer == nullptr) {
            return false;
        }
        BufferHandle *bufferHandle =  buffer->GetBufferHandle();
        if (bufferHandle == nullptr) {
            return false;
        }

        struct timeval now;
        gettimeofday(&now, nullptr);
        constexpr int secToUsec = 1000 * 1000;
        int64_t nowVal =  static_cast<int64_t>(now.tv_sec) * secToUsec + static_cast<int64_t>(now.tv_usec);
        std::string filename = "/data/SurfaceRenderNode_" +
            node.GetName() + "_"  +
            std::to_string(node.GetId()) + "_" +
            std::to_string(nowVal) + ".png";

        WriteToPngParam param;
        param.width = static_cast<uint32_t>(bufferHandle->width);
        param.height = static_cast<uint32_t>(bufferHandle->height);
        param.data = (uint8_t*)(buffer->GetVirAddr());
        param.stride = static_cast<uint32_t>(bufferHandle->stride);
        param.bitDepth = 8;

        return WriteToPng(filename, param);      
    }

    return false;
}

}// namespace Rosen
} // namespace OHOS


接下来我们要做的就是在OpenHarmony的处理逻辑中,调用什么的源码进行dump,具体操作步骤如下:

  • 在rs_render_service_visitor.cpp中引入上述头文件,并且在下面引入dump

    //foundation/graphic/graphic_2d/rosen/modules/render_service/core/pipeline/rs_render_service_visitor.cpp
    void RSRenderServiceVisitor::ProcessSurfaceRenderNode(RSSurfaceRenderNode& node)
    {
    	...
    	//不一定要在这个地方,只需要是渲染后对对应的RSSurfaceRenderNode操作即可
        RSBaseRenderUtil::WriteSurfaceRenderNodeToPng(node);
        ...
    }
    
  • 当我们想要dump时候,只需要将对应parma打开即可

    rosen.dump.rendernode
    
  • 接着就可以在data目录下看到生成的png图片
    在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述


1.2 dump OpenHarmony合成图层SurfaceBuffer

这块我们可以在hdi_backend.cpp的如下方法中添加相关的逻辑,如下:

int32_t HdiBackend::SetScreenClientInfo(const FrameBufferEntry &fbEntry, const OutputPtr &output)
{
	...
    RSBaseRenderUtil::WriteSurfaceBufferToPng(fbEntry.buffer);
    ...
}

这当然上述仅仅是提供了一种思路,具体的上述源码逻辑用在什么地方,读者可以根据自己的需要自行调整。这里我们简单测试一下,看看生成的dump文件如下:

在这里插入图片描述

在这里插入图片描述




二.OpenHarmony dump渲染和合成图层SurfaceBuffer指南小结和注意事项

到这里dump的相关逻辑就告一段落了,细心的朋友也许会发现dump渲染和合成的图层代码逻辑基本完全一致。是的,这是因为无论是渲染的图层还是合成之后的图层它们都是通过SurfaceBuffer来进行存储指向的。

其中,我们引用上述封装好的dump函数时候,我们在对应的BUILD.gn中必须,引入如下的库和头文件,如下

  deps = [
   "//foundation/graphic/graphic_2d:libsurface",
	"//foundation/graphic/graphic_2d/rosen/modules/render_service_base:librender_service_base",
  ]

  public_deps = [
    "//foundation/graphic/graphic_2d/utils:buffer_handle",
    "//third_party/libpng:libpng",
  ]
  external_deps = [ "init:libbegetutil" ]
  include_dirs = [
    "//drivers/peripheral/display/interfaces/include",
    "//third_party/libpng",
  ]

这里我们简单总结下dump OpenHarmony中各种图层SurfaceBuffer内容的思路:

  • 首先要获取各种图层所指向的GraphicBuffer
  • 获取GraphicBuffer的存储地址(通常是通过内存映射过来的)
  • 然后将获取到的地址中的内容,以一定的格式进行存储,通常是GRB888格式(也可以进行相关的封装)

这里重点补充一下,关于dump SurfaceBuffer获取的信息大小,格式,以及存储计算规则是否正确可以通过hidumper -s RenderService -a allInfo 进行查看,如下:

# hidumper  -s RenderService

-------------------------------[ability]-------------------------------


----------------------------------RenderService---------------------------------
------Graphic2D--RenderSerice ------
Usage:
 h                             |help text for the tool
screen                         |dump all screen infomation in the system
surface                        |dump all surface information
composer fps                   |dump the fps info of composer
[surface name] fps             |dump the fps info of surface
composer fpsClear                   |clear the fps info of composer
[surface name] fpsClear             |clear the fps info of surface
nodeNotOnTree                  |dump nodeNotOnTree info
allSurfacesMem                 |dump surface mem info
RSTree                         |dump RSTree info
EventParamList                 |dump EventParamList info
allInfo                        |dump all info


# hidumper  -s RenderService -a allInfo                                        


-------------------------------[ability]-------------------------------


----------------------------------RenderService---------------------------------
-- ScreenInfo
screen[0]: id=2, powerstatus=POWER_STATUS_ON, backlight=-1, screenType=EXTERNAL_TYPE
  supportedMode[0]: 720x400, refreshrate=70
  supportedMode[1]: 640x480, refreshrate=60
  supportedMode[2]: 640x480, refreshrate=75
  supportedMode[3]: 800x600, refreshrate=60
  supportedMode[4]: 800x600, refreshrate=75
  supportedMode[5]: 1024x768, refreshrate=60
  supportedMode[6]: 1152x864, refreshrate=75
  supportedMode[7]: 1280x1024, refreshrate=60
  supportedMode[8]: 1280x1024, refreshrate=75
  supportedMode[9]: 1920x1080, refreshrate=60
  activeMode: 1920x1080, refreshrate=60
  capability: name=Unknown, phywidth=530, phyheight=300,supportlayers=0, virtualDispCount=0, propCount=0, type=INVILID_DISP_INTF, supportWriteBack=false

-- LayerInfo

 surface [ScreenLockWindow] NodeId[2954937499653] LayerId[2]://锁屏界面
 zOrder = 0, visibleNum = 1, transformType = 0 <no rotation>, compositionType = 0 <client composistion>, blendType = 3 <SRC_OVER blending>, layerAlpha = [enGlobalAlpha(1), enPixelAlpha(0), alpha0(0), alpha1(0), gAlpha(255)].
 layerRect = [0, 0, 1920, 1080], visibleRegion = [0, 0, 1920, 1080], dirtyRegion = [0, 0, 1920, 1080], cropRect = [0, 0, 1920, 1080].
    BufferQueue:
      default-size = [1920x1080], FIFO = 3, name = ScreenLockWindow, uniqueId = 2954937499653, usedBufferListLen = 3, freeBufferListLen = 2, dirtyBufferListLen = 0, totalBuffersMemSize = 24300.00(KiB).
      bufferQueueCache:
        sequence = 8, state = 0 <released>, timestamp = 780011576923, damageRect = [0, 0, 1920, 1080], config = [1920x1080, 8, 12, 9, 3000], bufferWith = 1920, bufferHeight = 1080, bufferMemSize = 8100.00(KiB).
        sequence = 9, state = 0 <released>, timestamp = 840016378613, damageRect = [0, 0, 1920, 1080], config = [1920x1080, 8, 12, 9, 3000], bufferWith = 1920, bufferHeight = 1080, bufferMemSize = 8100.00(KiB).
        sequence = 13, state = 3 <acquired>, timestamp = 900011540119, damageRect = [0, 0, 1920, 1080], config = [1920x1080, 8, 12, 9, 3000], bufferWith = 1920, bufferHeight = 1080, bufferMemSize = 8100.00(KiB).

FrameBufferSurface
    BufferQueue:
      default-size = [0x0], FIFO = 3, name = FrameBuffer, uniqueId = 2954937499648, usedBufferListLen = 2, freeBufferListLen = 1, dirtyBufferListLen = 0, totalBuffersMemSize = 16200.00(KiB).
      bufferQueueCache:
        sequence = 2, state = 3 <acquired>, timestamp = 900046439, damageRect = [0, 0, 1920, 1080], config = [1920x1080, 8, 12, 73, 3000], bufferWith = 1920, bufferHeight = 1080, bufferMemSize = 8100.00(KiB).
        sequence = 4, state = 0 <released>, timestamp = 840051447, damageRect = [0, 0, 1920, 1080], config = [1920x1080, 8, 12, 73, 3000], bufferWith = 1920, bufferHeight = 1080, bufferMemSize = 8100.00(KiB).

-- Node Not On Tree

 node Id[6597069766667]:
    BufferQueue:
      default-size = [0x0], FIFO = 3, name = SystemUi_BannerNotice, uniqueId = 2954937499659, usedBufferListLen = 0, freeBufferListLen = 0, dirtyBufferListLen = 0, totalBuffersMemSize = 0.00(KiB).
      bufferQueueCache:

 node Id[6597069766666]:
    BufferQueue:
      default-size = [0x0], FIFO = 3, name = SystemUi_DropdownPanel, uniqueId = 2954937499658, usedBufferListLen = 0, freeBufferListLen = 0, dirtyBufferListLen = 0, totalBuffersMemSize = 0.00(KiB).
      bufferQueueCache:

 node Id[6597069766658]:
    BufferQueue:
      default-size = [0x0], FIFO = 3, name = SystemUi_VolumePanel, uniqueId = 2954937499654, usedBufferListLen = 0, freeBufferListLen = 0, dirtyBufferListLen = 0, totalBuffersMemSize = 0.00(KiB).
      bufferQueueCache:

 node Id[7146825580544]:
    BufferQueue:
      default-size = [0x0], FIFO = 3, name = imeWindow, uniqueId = 2954937499652, usedBufferListLen = 0, freeBufferListLen = 0, dirtyBufferListLen = 0, totalBuffersMemSize = 0.00(KiB).
      bufferQueueCache:

 node Id[6962141986820]:
    BufferQueue:
      default-size = [0x0], FIFO = 3, name = RecentView, uniqueId = 2954937499651, usedBufferListLen = 0, freeBufferListLen = 0, dirtyBufferListLen = 0, totalBuffersMemSize = 0.00(KiB).
      bufferQueueCache:

-- All Surfaces Memory Size
the memory size of all surfaces buffer is : 94680.00 KiB.
    BufferQueue:
      default-size = [0x0], FIFO = 3, name = SystemUi_DropdownPanel, uniqueId = 2954937499658, usedBufferListLen = 0, freeBufferListLen = 0, dirtyBufferListLen = 0, totalBuffersMemSize = 0.00(KiB).
      bufferQueueCache:
    BufferQueue:
      default-size = [1920x32], FIFO = 3, name = SystemUi_PrivacyIndicator, uniqueId = 2954937499657, usedBufferListLen = 3, freeBufferListLen = 1, dirtyBufferListLen = 0, totalBuffersMemSize = 720.00(KiB).
      bufferQueueCache:
        sequence = 12, state = 1 <requested>, timestamp = 40645170158, damageRect = [0, 0, 1920, 32], config = [1920x32, 8, 12, 9, 3000], bufferWith = 1920, bufferHeight = 32, bufferMemSize = 240.00(KiB).
        sequence = 14, state = 3 <acquired>, timestamp = 40912469187, damageRect = [0, 0, 1920, 32], config = [1920x32, 8, 12, 9, 3000], bufferWith = 1920, bufferHeight = 32, bufferMemSize = 240.00(KiB).
        sequence = 17, state = 0 <released>, timestamp = 40827680126, damageRect = [0, 0, 1920, 32], config = [1920x32, 8, 12, 9, 3000], bufferWith = 1920, bufferHeight = 32, bufferMemSize = 240.00(KiB).
    BufferQueue:
      default-size = [1920x1080], FIFO = 3, name = EntryView, uniqueId = 2954937499650, usedBufferListLen = 3, freeBufferListLen = 2, dirtyBufferListLen = 0, totalBuffersMemSize = 24300.00(KiB).
      bufferQueueCache:
        sequence = 5, state = 0 <released>, timestamp = 31794906265, damageRect = [0, 0, 1920, 1080], config = [1920x1080, 8, 12, 9, 3000], bufferWith = 1920, bufferHeight = 1080, bufferMemSize = 8100.00(KiB).
        sequence = 6, state = 0 <released>, timestamp = 32561536655, damageRect = [0, 0, 1920, 1080], config = [1920x1080, 8, 12, 9, 3000], bufferWith = 1920, bufferHeight = 1080, bufferMemSize = 8100.00(KiB).
        sequence = 7, state = 3 <acquired>, timestamp = 32644867137, damageRect = [0, 0, 1920, 1080], config = [1920x1080, 8, 12, 9, 3000], bufferWith = 1920, bufferHeight = 1080, bufferMemSize = 8100.00(KiB).
    BufferQueue:
      default-size = [1920x108], FIFO = 3, name = SystemUi_NavigationBar, uniqueId = 2954937499656, usedBufferListLen = 3, freeBufferListLen = 2, dirtyBufferListLen = 0, totalBuffersMemSize = 2430.00(KiB).
      bufferQueueCache:
        sequence = 11, state = 0 <released>, timestamp = 40827680126, damageRect = [0, 0, 1920, 108], config = [1920x108, 8, 12, 9, 3000], bufferWith = 1920, bufferHeight = 108, bufferMemSize = 810.00(KiB).
        sequence = 16, state = 0 <released>, timestamp = 40912469187, damageRect = [0, 0, 1920, 108], config = [1920x108, 8, 12, 9, 3000], bufferWith = 1920, bufferHeight = 108, bufferMemSize = 810.00(KiB).
        sequence = 19, state = 3 <acquired>, timestamp = 60012066524, damageRect = [0, 0, 1920, 108], config = [1920x108, 8, 12, 9, 3000], bufferWith = 1920, bufferHeight = 108, bufferMemSize = 810.00(KiB).
    BufferQueue:
      default-size = [0x0], FIFO = 3, name = SystemUi_VolumePanel, uniqueId = 2954937499654, usedBufferListLen = 0, freeBufferListLen = 0, dirtyBufferListLen = 0, totalBuffersMemSize = 0.00(KiB).
      bufferQueueCache:
    BufferQueue:
      default-size = [1920x1080], FIFO = 3, name = ScreenLockWindow, uniqueId = 2954937499653, usedBufferListLen = 3, freeBufferListLen = 2, dirtyBufferListLen = 0, totalBuffersMemSize = 24300.00(KiB).
      bufferQueueCache:
        sequence = 8, state = 0 <released>, timestamp = 780011576923, damageRect = [0, 0, 1920, 1080], config = [1920x1080, 8, 12, 9, 3000], bufferWith = 1920, bufferHeight = 1080, bufferMemSize = 8100.00(KiB).
        sequence = 9, state = 0 <released>, timestamp = 840016378613, damageRect = [0, 0, 1920, 1080], config = [1920x1080, 8, 12, 9, 3000], bufferWith = 1920, bufferHeight = 1080, bufferMemSize = 8100.00(KiB).
        sequence = 13, state = 3 <acquired>, timestamp = 900011540119, damageRect = [0, 0, 1920, 1080], config = [1920x1080, 8, 12, 9, 3000], bufferWith = 1920, bufferHeight = 1080, bufferMemSize = 8100.00(KiB).
    BufferQueue:
      default-size = [0x0], FIFO = 3, name = imeWindow, uniqueId = 2954937499652, usedBufferListLen = 0, freeBufferListLen = 0, dirtyBufferListLen = 0, totalBuffersMemSize = 0.00(KiB).
      bufferQueueCache:
    BufferQueue:
      default-size = [0x0], FIFO = 3, name = RecentView, uniqueId = 2954937499651, usedBufferListLen = 0, freeBufferListLen = 0, dirtyBufferListLen = 0, totalBuffersMemSize = 0.00(KiB).
      bufferQueueCache:
    BufferQueue:
      default-size = [1920x108], FIFO = 3, name = SystemUi_StatusBar, uniqueId = 2954937499655, usedBufferListLen = 3, freeBufferListLen = 2, dirtyBufferListLen = 0, totalBuffersMemSize = 2430.00(KiB).
      bufferQueueCache:
        sequence = 10, state = 0 <released>, timestamp = 40827680126, damageRect = [0, 0, 1920, 108], config = [1920x108, 8, 12, 9, 3000], bufferWith = 1920, bufferHeight = 108, bufferMemSize = 810.00(KiB).
        sequence = 15, state = 3 <acquired>, timestamp = 60012066524, damageRect = [0, 0, 1920, 108], config = [1920x108, 8, 12, 9, 3000], bufferWith = 1920, bufferHeight = 108, bufferMemSize = 810.00(KiB).
        sequence = 18, state = 0 <released>, timestamp = 40912469187, damageRect = [0, 0, 1920, 108], config = [1920x108, 8, 12, 9, 3000], bufferWith = 1920, bufferHeight = 108, bufferMemSize = 810.00(KiB).

-- RenderServiceTreeDump: 
Animating Node: [];
| BASE_NODE[0], isOnTheTree: 1, children[2963527434241 ]
  | DISPLAY_NODE[2963527434241], isOnTheTree: 1, children[6597069766656 6597069766661 6597069766664 6597069766665 6962141986816 ]
    | SURFACE_NODE[6597069766656], isOnTheTree: 1, hasConsumer: 1, Name [ScreenLockWindow], parent [2963527434241], { Region Size 1: [0, 0, 1920, 1080] }, SurfaceBgAlpha[ 255 ], children[]
    | SURFACE_NODE[6597069766661], isOnTheTree: 1, hasConsumer: 1, Name [SystemUi_StatusBar], parent [2963527434241], { Region Size 0:  }, SurfaceBgAlpha[ 0 ], children[]
    | SURFACE_NODE[6597069766664], isOnTheTree: 1, hasConsumer: 1, Name [SystemUi_NavigationBar], parent [2963527434241], { Region Size 0:  }, SurfaceBgAlpha[ 0 ], children[]
    | SURFACE_NODE[6597069766665], isOnTheTree: 1, hasConsumer: 1, Name [SystemUi_PrivacyIndicator], parent [2963527434241], { Region Size 0:  }, SurfaceBgAlpha[ 0 ], children[]
    | SURFACE_NODE[6962141986816], isOnTheTree: 1, hasConsumer: 1, Name [EntryView], parent [2963527434241], { Region Size 0:  }, SurfaceBgAlpha[ 0 ], children[]

-- EventParamListDump: 
rosen.RsDFXEvent.RS_COMPOSITION_TIMEOUT.timeOutThresholdMs: 100
rosen.RsDFXEvent.RS_COMPOSITION_TIMEOUT.eventIntervalMs: 60000
-- QosDump: 
QOS is disabled




三.写在最后

至此OpenHarmony dump渲染和合成图层SurfaceBuffer指南整个就完成了,读者是感到意犹未尽呢,还是想说一句尼玛,瞎扯淡呢!
好了,OpenHarmony dump渲染和合成图层SurfaceBuffer指南就告一段落了,各位青山不改绿水长流,各位江湖见!当然各位读者的点赞和关注是我写作路上前进的最大动力了,如果有啥不对或者不爽的也可以踩一踩也无妨!你们的鼓励和批评是博主前进路上最大的动力。

各位读友,千万不要喷我,因为我这也是第一次深入到OpenHarmony显示这块的源码逻辑,为啥我深入到了这块,因为入职了一家原厂。所以我现在是菜鸟一杯,如果有对OpenHarmony graphic刚兴趣的朋友,也可以联系我,一起学习进步!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

OpenHarmony dump渲染和合成图层SurfaceBuffer指南 的相关文章

  • 润和HCIP认证套件的烧写问题的终极解决方案

    目录 问题的由来 烧写问题 启动问题 总结 问题的由来 润和HarmonyOS鸿蒙开发板 HiSpark AI Camera开发套件 下图 是OpenHarmony的小型设备和标准设备的代表 基于华为海思Hi3516DV300芯片 支持Li
  • OpenHarmony之docker容器的基本用法

    Docker使用示例 docker移植至OpenHarmony的过程可参考 https blog 51cto com u 14601312 5692202 下面以rk3568 OpenHarmony为例 介绍一下如何进行容器制作 导入及使用
  • VCS命令行CTRL+C后dump完整的fsdb波形

    UCLI命令行CTRL C后dump完整的fsdb波形 1 ucli fsdbDumpFinish 2 ucli fsdbDumpvars 0 harness mda struct 如果仿真过程中直接CTRL C会调到UCLI接口 此时如果
  • GD32F4xx适配OpenHarmony问题踩坑记录

    1 时钟配置导致的串口乱码 现象描述 最新在适配GD32产品时 发现使用外部晶振时调试串口输出内容会出现乱码 使用内部晶振则不会出现这个问题 配置如下所示 后来研究了半天 发现GD32除了配置system gd32f4xx h中的时钟倍频宏
  • 【OpenHarmony】L1 烧录的启动参数

    OpenHarmony L1 烧录的启动参数 启动参数 linux liteos a uboot位置 linux liteos a和linux共用 启动参数 linux setenv bootargs mem 128M console tt
  • Hi3516全系统类型烧录教程

    烧录资料下载 https gitee com hihope iot docs tree master HiSpark AI Camera Developer Kit Software tools 第一步 安装好hitool usb 烧写的驱
  • 为什么单个修订版的 SVN 转储比完整转储大?

    我的存储库是2 5G 通过转储svnadmin dump myrepos gt dumpfile是5G 但是当我像这样转储时svnadmin dump myrepos r 23785 gt rev 23785 dumpfile其中 2378
  • 禁用 JVM 上的本地 JMX 连接

    我们正在编写一个在内存中保存密码的java程序 不幸的是 用户可以轻松地使用 jconsole 或 jmap 创建堆转储文件并打开它来查找密码 我认为 jconsole 使用本地套接字连接 jvm 我想知道 有什么方法可以禁用本地用户的 j
  • 鸿蒙开发之页面路由(router)

    页面路由 router 页面路由指在应用程序中实现不同页面之间的跳转和数据传递 HarmonyOS提供了Router模块 通过不同的url地址 可以方便地进行页面路由 轻松地访问不同的页面 本文将从 页面跳转 页面返回 和 页面返回前增加一
  • 如何从 mysql 表中转储 blob 字段

    我正在尝试从 mysql 表中转储 BLOB 字段 但是当我使用 sqlYog 转储 blob 记录时 我得到了无价值的数据 如何备份 BLOB 类型字段 Note BLOB 字段有图像 参数 十六进制斑点当您打算将其导入到另一个数据库 如
  • 当从 IntelliJ 运行并使用 setcap 赋予网络嗅探权限时,Java 每隔几秒输出一次完整线程转储

    我正在编写一个使用 Pcap 库进行数据包嗅探的应用程序 为了让它发挥作用 我需要给出java二进制网络嗅探功能 以避免必须将其运行为root sudo setcap cap net raw cap net admin eip path t
  • Windows 转储文件格式

    我一直致力于创建更好的工具来处理我的组织中的转储 对于核心转储 linux 这很简单 因为它们是具有已知格式的 ELF 文件 然而 我们有一些 Windows 系统 它们生成的转储似乎不是 ELF 我知道有 Windows 工具可以处理这些
  • H2DB 中如何像 MySql 中那样获取 sql 转储?

    我有 H2DB 数据库 它将数据存储在文件中 我有3个文件 test 18 log db test data db and test index db 我想要像我使用时一样获取 SQL 转储文件mysqldump 是否可以 是的 有多种解决
  • OpenHarmony沙箱文件

    一 前言 1 前景提要 DevEcoStudio版本 DevEco Studio 3 1 Release SDK版本 3 2 2 5 API版本 9 2 概念 在openharmony文件管理模块中 按文件所有者分类分为应用文件和用户文件和
  • 如何将 postgres 数据库转换为 SQLite?

    我们正在开发一个网站 当我们在本地开发时 其中一个来自Windows 我们使用sqlite3 但在服务器 linux 上我们使用postgres 我们希望能够将生产数据库导入到我们的开发过程中 所以我想知道是否有一种方法可以将 postgr
  • 有没有办法使用增量更新 SQLITE 数据库?

    我想知道 SQLite 是否提出了基于某些增量文件的更新机制 例如 Oracle 数据库可以与 sql 重做日志或快照日志同步 SQLite是否提出了一种优化机制来更新自身 我的用例如下 我有一个本地数据库 必须与一些远程数据同步 在理想的
  • JavaScript 中相当于 PHP 中的 var_dump 或 print_r 的是什么? [复制]

    这个问题在这里已经有答案了 我想查看 JavaScript 中对象的结构 用于调试 PHP中有类似var dump的东西吗 大多数现代浏览器的开发工具中都有一个控制台 对于此类调试很有用 console log myvar 然后 您将在控制
  • 如何在Python中正确编码json转储[重复]

    这个问题在这里已经有答案了 我有一个 python 3 脚本 应该从 csv 文件获取一些数据并将其写入 json 文件 在我的处理过程中 编码是正确的 因此德语变音 或度数符号 就像它们本来的样子 coding cp1252 在头部 但是
  • 如何使用 mysqldump 跳过某些数据库表?

    有没有办法限制 mysqldump 命令中的某些表 例如 我将使用以下语法来转储only table1 and table2 mysqldump u username p database table1 table2 gt database
  • 使用mysqldump只转储数据,不转储任何表信息

    我正在寻找转储 mysql 数据库中所有数据的语法 我不需要任何表格信息 mysqldump no create info 您也可以使用 skip triggers 如果您使用触发器 no create db 如果您正在使用 databas

随机推荐

  • C#读取文本文件

    根据文件名到对应文件夹中读取对应文本文件 txt 并返回数据集合 使用流读取类StreamReader 一行一行读取 ReadLine 文本格式 public static List
  • 使用connect by进行级联查询

    connect by可以用于级联查询 常用于对具有树状结构的记录查询某一节点的所有子孙节点或所有祖辈节点 来看一个示例 现假设我们拥有一个菜单表t menu 其中只有三个字段 id name和parent id 它们是具有父子关系的 最顶级
  • Ubuntu22安装Redis

    Redis 是一个开源的在内存存储键值对数据的存储程序 它可以被用作数据库 缓存 信息暂存 并且支持各种数据结构 例如 字符串 哈希值 列表 集合等等 Redis 通过 Redis Sentinel 和 Redis 集群中多个 Redis
  • 解决谷歌人机验证(Captcha)显示问题

    文章目录 前言 一 Header Editor 下载 安装与配置 1 插件下载 2 插件安装 3 插件配置 前言 由于谷歌服务在国内不可用 所以正常访问时某些网址时 经常会出现需要人机验证的问题 影响正常使用 在不使用科学上网的情况下 我们
  • Web启动项目走Https协议(Webpack版,Umi版和Host代理版)

    需求 Web项目的启动 一般是默认的http协议 在某些业务需求时 需要走https来调试 Webpack版本 只需在webpack的devServer中配置就可以了 devServer host 0 0 0 0 port 8080 htt
  • html代码制作的个人简历源代码

  • python requests.get post

    get 方式 首先导入requests库 import requests 定义url url https baidu com 定义请求头 注意的是headers在真实环境中是有很多数据的 我们通过python传输这个数据就要以字典的方式来定
  • windows10系统提示不允许使用你正在尝试的登录方式,请联系网络管理员了解详细信息

    故障截图如图所示 排查方法 1 检查AD域用户账号登录到是否受限 2 在运行框中输入gpedit msc查看组策略 计算机配置 windows设置 本地配置 用户权限分配 拒绝本地登录 guest 参考是否与正常登录的用户电脑设置一致 允许
  • 使用ESP8266接入“天猫精灵”控制七彩灯(WS2812)的颜色/亮度-开源

    目录 演示视频 1 准备工作 1 1 原理 1 2 使用的硬件以及硬件连接图 1 3 开发环境准备 Arduino开发环境 安装ESP8266的扩展 安装blinker Arduino库 安装blinker APP 下载ws2812的驱动库
  • 树莓派_超声波传感器_三色LED

    import RPi GPIO as GPIO import time TRIG 26 ECHO 19 GREEN 6 YELLOW 5 RED 13 GPIO setmode GPIO BCM GPIO setwarnings False
  • 仿射系统和非仿射系统的数学定义

    一 非仿射系统 非仿射系统是指系统的输入是以非线性的形式出现的 例如 u 2 sin u 等 12 非仿射系统可以用下面的一般形式表示 x t f x t g x t h u t 其中 x t 是状态变量 u t 是控制输入 f x 和 g
  • Codeforces-1260-E. Tournament贪心

    题目描述 You are organizing a boxing tournament where n boxers will participate n is a power of 2 and your friend is one of
  • 利用celebA数据集训练MTCNN网络

    利用celebA数据集训练MTCNN网络 celebA数据集简介 训练数据的处理 网络和训练 侦测部分 结果展示 有问题可以联系我的邮箱 2487429219 qq com 关于MTCNN网络可以看我上一篇博客 链接 人脸检测算法 mtcn
  • 请用C + +语言写一个生成随机数程序

    include
  • windows系统更改远程桌面端口

    开启远程桌面 我的电脑属性 远程设置 步骤一 在服务器运行窗口中输入 regedit 打开注册表编辑器 步骤二 在注册表HKEY LOCAL MACHINE SYSTEM CurrentControlSet Control Terminal
  • 注解-Annotation Types学习

    前言 注解是JDK5 之后推出的特性 可修饰包 类 方法 变量等 通过在编译 加载和运行时读取其信息 可执行相应的处理 基本原理 java注解类型实质上是一个标记 如 Autowired private TestBean testBean
  • win10家庭中文版开启Hyper-V功能

    问题描述 由于win10家庭中文版是被阉割过的 有些功能就被禁用了 启用和禁用程序中就没有了Hyper V功能 如果想要更多的功能可以将系统升级成为专业版和企业版即可解决 但如果想直接在家庭中文版下创建也是可行 这里有一位大神给出了自己的方
  • LeetCode题解--160. 相交链表

    题目 编写一个程序 找到两个单链表相交的起始节点 例如 下面的两个链表 A a1 a2 c1 c2 c3 B b1 b2 b3 在节点 c1 开始相交 注意 如果两个链表没有交点 返回 null 在返回结果后 两个链表仍须保持原有的结构 可
  • html5中拖放,HTML5中的拖放

    关于HTML5中的拖放 拖放 Drag 和 Drop 是一种常见的特性 即抓取对象以后拖到另一个位置 在 HTML5 中 拖放是标准的组成部分 在HTML5中用户可以使用鼠标选择一个可拖动元素 将元素拖动到一个可放置元素 并通过释放鼠标按钮
  • OpenHarmony dump渲染和合成图层SurfaceBuffer指南

    OpenHarmony dump渲染和合成图层SurfaceBuffer指南 引言 博客停更很久了 提起笔来渐感生疏啊 看来 还是得抽出时间来更新更新啊 好了 感慨也发完了 是时候切入正题了 本篇博客主要以本人在实际项目的开发中 为了定位O