从bootanimation出发分析OpenHarmony下Gralloc buffer管理机制

news2024/12/24 21:36:29

    从bootanimation出发分析OpenHarmony下Gralloc buffer管理机制



引言

  这个文档主要记录从bootanimation角度出发,分析OpenHarmony下对gralloc buffer的管理!由于OpenHarmony图形子系统过于复杂,且个人由于能力有限,这里我仅从gralloc buffer出发,从整体上对Gralloc buffer进行梳理!虽然过程会很艰辛,但是我一定要坚持下来。加油!加油!加油!

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

foundation/graphic/graphic_2d/frameworks/bootanimation/src/
foundation/graphic/graphic_2d/rosen/modules/render_service_client/core/ui/
foundation/window/window_manager/wm/src/
foundation/graphic/graphic_2d/rosen/modules/render_service_base/src/platform/ohos/
foundation/graphic/graphic_2d/rosen/modules/render_service/core/pipeline/
device/soc/phytium/d2000/hardware/display/



一.bootamitin核心流程分析

  bootamitin的核心功能是播放开机动画,其中会涉及到音频播放这块我们可以忽视。既然其中涉及开机动画的播放,那么就和graphics有关。我们正好可以拿这块来作为gralloc buffer管理来分析。这里我只放出核心的步骤,具体的在后面分析:

//boot_animation.cpp
  BootAnimation::Init
    auto& rsClient = OHOS::Rosen::RSInterfaces::GetInstance()
    receiver_ = rsClient.CreateVSyncReceiver("BootAnimation", mainHandler_)//注册Vsync监听
    receiver_->Init()//初始化
    InitBootWindow()//创建窗口
      scene_ = new OHOS::Rosen::WindowScene();
      window_ = scene_->GetMainWindow()
      scene_->Init(displayId, nullptr, listener, option)
      window_ = scene_->GetMainWindow()
    rsSurface_ = OHOS::Rosen::RSSurfaceExtractor::ExtractRSSurface(window_->GetSurfaceNode());  //此处是重点,surface的创建
    OHOS::Rosen::VSyncReceiver::FrameCallback fcb = {
        .userData_ = this,
        .callback_ = std::bind(&BootAnimation::OnVsync, this),//其中OnVsync响应Vsync事件
    };
    int32_t changefreq = static_cast<int32_t>((1000.0 / freq_) / 16);
    ret = receiver_->SetVSyncRate(fcb, changefreq);//发送VSync监听到周期变化

  BootAnimation::OnVsync(...)
    PostTask(std::bind(&BootAnimation::Draw, this))
    BootAnimation::Draw()
      //申请一个buffer
      auto frame = rsSurface_->RequestFrame(windowWidth_, windowHeight_)
      canvas = framePtr_->GetCanvas();
      rsSurface_->FlushFrame(framePtr_)

上述的流程是bootanimation的核心流程,其中几个核心在于:

  • rsSurface_的创建过程
  • RequestFrame的执行流程(主要涉及渲染buffer的申请)
  • FlushFrame的流程(渲染buffer,flush到消费端)



二.rsSurface的创建

2.1 RSSurface rsSurface_的创建

  • 具体调用流程如下:
rsSurface_ = OHOS::Rosen::RSSurfaceExtractor::ExtractRSSurface(window_->GetSurfaceNode());//这里的rsSurfa指向RSSurfaceOhosGl
	window_->GetSurfaceNode() = CreateSurfaceNode(property_->GetWindowName(), option->GetWindowType()) // window_impl.cpp
		RSSurfaceNode::Create(rsSurfaceNodeConfig, rsSurfaceNodeType)
			RSSurfaceNode::CreateNodeAndSurface
				RSRenderServiceClient->CreateNodeAndSurface(...)
					 auto renderService = RSRenderServiceConnectHub::GetRenderService();//这里获取的是RSRenderServiceConnectionProxy代理端
						RSRenderServiceConnectHub::GetRenderServiceConnection
							sptr<RSIRenderServiceConnection> conn = renderService->CreateConnection(token_);
					 sptr<Surface> surface = renderService->CreateNodeAndSurface(config); //调用到服务端,这里使用的是IPC调用
					 CreateRSSurface(surface)
						producer = std::make_shared<RSSurfaceOhosGl>(surface);

//客户端调用流程
sptr<Surface> surface = renderService->CreateNodeAndSurface(config);//注意这里的renderService是代理端
	Remote()->SendRequest(RSIRenderServiceConnection::CREATE_NODE_AND_SURFACE, data, reply, option);  //通过ipc传输,跨进程调用
		sptr<Surface> surface = CreateNodeAndSurface(config);//rs_render_connection_stub.cpp
			node = RSSurfaceRenderNode(...)
			surface = Surface::CreateSurfaceAsConsumer(config.name);//作为消费端
			node->SetConsumer(surface);
    			std::weak_ptr<RSSurfaceRenderNode> surfaceRenderNode(node); //创建RSSurfaceRenderNode
    			sptr<IBufferConsumerListener> listener = new RSRenderServiceListener(surfaceRenderNode);
   			SurfaceError ret = surface->RegisterConsumerListener(listener);//注册回调监听
        sptr<IRemoteObject> surfaceObject = reply.ReadRemoteObject();
        sptr<IBufferProducer> bp = iface_cast<IBufferProducer>(surfaceObject);//这个地方IBufferProducer具体的指向,这个是BufferClientProducer
        sptr<Surface> surface = Surface::CreateSurfaceAsProducer(bp);


//render_service服务端调用流程
        sptr<Surface> surface = CreateNodeAndSurface(config);
		RSRenderServiceConnection::CreateNodeAndSurface(...)//rs_render_service_connection.cpp
			RSSurfaceRenderNode node = std::make_shared<RSSurfaceRenderNode>(...)
			surface = Surface::CreateSurfaceAsConsumer(...)

            auto producer = surface->GetProducer();
            reply.WriteRemoteObject(producer->AsObject());  //这里跨进程传递的是代理端


  • 其中IBufferProducer的IPC客户端和服务端的实现如下(其中类似的实现还有RSIRenderServiceConnection,可以类比Android中的SurfaceFlinger中nnection的实现)):

在这里插入图片描述


  • 其中RSIRenderServiceConnection的类图关系如下:

在这里插入图片描述


  • 其中Surface之间的类图关系如下:

在这里插入图片描述




三.RequestFrame流程

3.1 RequestFrame的流程

  • 具体的调用流程如下:

    rsSurface_->RequestFrame(windowWidth_, windowHeight_);
    	RSSurfaceOhosGl::RequestFrame  //rs_surface_ohos_gl.cpp
    		RenderContext* context = GetRenderContext()
    		mWindow = CreateNativeWindowFromSurface(&producer_)
    			nativeWindow->surface = *reinterpret_cast<OHOS::sptr<OHOS::Surface> *>(pSurface);//这个地方的pSurface有啥作用呢,传入到Mesa中去了
    		mEglSurface = context->CreateEGLSurface
    		frame = RSSurfaceFrameOhosGl
    		context->MakeCurrent(mEglSurface)
    		frame->SetRenderContext(context)
    
    
  • 需要注意的点:

    在bootanimation主要是通过egl配合gl进行渲染操作,那么前面创建的rsSurface_还有啥作用呢:
    1.主要是将该rsSurface传入到Mesa
    2.在后续的使用中,在Mesa实现的EGL上面创建EGLSurface并将其传递给EGL,然后EGL也将该surface传递
    3.然后后续一些调用中就会通过psurface接口调用相关的request和acquiire和release操作




四.FlushFrame流程

4.1 FlushFrame的流程

  • 具体的调用流程如下:
rsSurface_->FlushFrame
	RSSurfaceOhosGl::FlushFrame	//rs_surface_ohos_gl.cpp
		context->SwapBuffers(mEglSurface)
			eglSwapBuffers(...)//render_context.cpp
				disp->Driver->SwapBuffers(...)  //eglapi.c
					SwapBuffers = dri2_swap_buffers
					dri2_dpy->vtbl->swap_buffers(disp, surf)
						ohos_swap_buffers()
						ohos_window_enqueue_buffer
						ANativeWindow_queueBuffer
						NativeWindowFlushBuffer
							window->surface->FlushBuffer(buffer->sfbuffer, acquireFence, config) //produce_surface.cpp
								producer_->FlushBUffer(...)//buffer_client_producer.cpp
									IPC send BUFFER_PRODUCER_FLUSH_BUFFER //跨进程调用到render_service

服务端响应:
BufferQueueProducer::FlushBufferRemote(...)//buffer_queue_producer.cpp
	BufferQueueProducer::Flush(...)
		bufferQueue_->FlushBuffer(...)//这里的bufferQueue指向BufferQueue
		DoFlushBuffer(...)
		listener_->OnBufferAvailable()//通知有渲染完成了,后续会触发vsync,这个地方跟下
			sptr<IBufferConsumerListener> listener = new RSRenderServiceListener(surfaceRenderNode);
    			SurfaceError ret = surface->RegisterConsumerListener(listener);//此处的listener是在rs_render_service_connection.cpp被注册回调
				RSRenderServiceListener::OnBufferAvailable(...)
					RSMainThread::Instance()->RequestNextVSync(...)//触发下次vsync,且此处的是一个全局的






五.RequestBuffer流程

5.1 RequestBuffer流程分析

  • 具体调用流程如下:
NativeWindowRequestBuffer(...) //native_window.cpp //客户端发出请求
	window->surface->RequestBuffer(...)
		 producer_->RequestBuffer(...)//buffer_client_producer.cpp
			SEND_REQUEST(BUFFER_PRODUCER_REQUEST_BUFFER, arguments, reply, option);
			ReadSurfaceBufferImpl(reply, retval.sequence, retval.buffer)



BufferQueueProducer::RequestBufferRemote	//render_service服务端响应
	RequestBuffer(.)
		bufferQueue_->RequestBuffer(...)//buffer_queue.cpp,这一部分有时间的话需要更加精细化的去分析,主要是分析buffer的管理部分
			AllocBuffer(...)//这里我们默认没有足够的buffer,需要重新创建
				SurfaceBuffer bufferImpl = new SurfaceBufferImpl()
				bufferImpl->Alloc(..)
					displayGralloc_->AllocMem(info, handle);//DisplayGrallocClient,通过gralloc服务进行分配,这里的displayGralloc_是gralloc服务的客户端
							 allocatorProxy_->AllocMem(...) //allocator_proxy.cpp
								Remote()->SendRequest(CMD_REMOTE_ALLOCATOR_ALLOCMEM, data, reply, option)//调用到服务端
								retHandle = ReadBufferHandle(reply)
				bufferImpl->Map(...)//映射到用户空间,这里木有通过gralloc服务
	WriteSurfaceBufferImpl(reply, retval.sequence, retval.buffer)//将申请到的buffer写回服务端,这其中需要注意的是会会有一次dup操作


###disp_gralloc_bo服务端接收请求
AllocatorServiceStub::OnRemoteRequest(...)//接收CMD_ALLOCATOR_ALLOCMEM命令,allocator_service_stub.cpp
	AllocaltorStubAllocMem(...)
		AllocMeme(...) //allocator_service_impl.cpp
			grallocFuncs_->AllocMem(...)\\disp_gralloc.c
				GbmGrallocMem(...)//display_gralloc_gbm.c
					hdi_gbm_bo_create(...)
						drmIoctl(gbm->fd, DRM_IOCTL_MODE_CREATE_DUMB, &dumb)
					hdi_gbm_bo_get_fd(...)
						drmPrimeHandleToFD(bo->gbm->fd, bo->handle, DRM_CLOEXEC | DRM_RDWR, &fd)
					InitBufferHandle(bo, fd, info, priBuffer)
					hdi_gbm_bo_destroy(...)
						drmIoctl(bo->gbm->fd, DRM_IOCTL_MODE_DESTROY_DUMB, &dumb)
		WriteBufferHandle(...)
		FreeMem(...)//注意这个地方并不是把buffer释放了,只是把dup前的fd释放了
  • gralloc跨进程调用简图:

在这里插入图片描述

这里我们可以看到RequestBuffer的调用过程中,牵涉到多次的IPC跨进程调用,其中核心的就是传递dumb的fd。


5.2 RequestBuffer过程中的几次dup

  • 核心点这里通过前面的总结可以看出,在RequestBuffer中一共有经历过两次dup操作!
//前面说的存在两次dup操作,都存在于服务端返回fd的时候,会分别调用WriteSurfaceBufferImpl(...)和WriteBufferHandle(...),我们下面对上述两个函数分贝展开来看看:

void WriteSurfaceBufferImpl(MessageParcel &parcel,
    uint32_t sequence, const sptr<SurfaceBuffer> &buffer)
{
    ...
    buffer->WriteToMessageParcel(parcel);
}

GSError SurfaceBufferImpl::WriteToMessageParcel(MessageParcel &parcel)
{

    ...
    bool ret = WriteBufferHandle(parcel, *handle);//后面调用的也是这个接口
    ...
}

bool WriteBufferHandle(MessageParcel &parcel, const BufferHandle &handle)
{
	...

    if (validFd && !parcel.WriteFileDescriptor(handle.fd)) {
        UTILS_LOGE("%{public}s parcel.WriteFileDescriptor fd failed", __func__);
        return false;
    }

	...
}

bool MessageParcel::WriteFileDescriptor(int fd)
{
    ...
    int dupFd = dup(fd);
    ...
}


参考:

Android Binder传递文件描述符原理分析




六.小结

  至此,以bootanimation为例说明的,OH下gralloc buffer管理就基本结束了。由于时间和个人能力的原因,总结的不是非常的彻底和到位,其中还有很多的地方只是简单的概括或者待过了。如果开发者或者读者有过Android graphcis相关经验的话,理解起来就比较容易了。这里我们可以使用如下的图示来概括下gralloc buffer的管理模式:

在这里插入图片描述

上述图示有如下几点需要注意:

  • 上述不但可以表述渲染buffer的管理模型,也可使是在使用GPU合成时framebuffer的模型图
  • 上述生产者和消费者可以位于不同的进程,也可以是同一个进程,绝大部分的时候位于不同的进程

从上面的总结可以看出:

  • gralloc buffer的模型就是一种典型的生产,消费者模型。应用申请gralloc buffer渲染完成之后,归还给bufferqueue
  • 消费者在收到vsync之后,从bufferqueue取出已经生产好的buffer,做进一步处理
  • 当进行GPU合成时,会拿到前面已经生产好的buffer,再在framebuffer中进行合成
  • 还有就是我们一定要有一个概念,就是应用端和render_server并不是直接进行通信的,而是通过IPC机制进行的。正是由于IPC机制设计的巧妙,是使用者以为是直接在和服务端交互。其实不然!



七.关于OH下graphics图形栈调试小技巧

  对于OH我们不要要求太多,肯定不能像Android那样提供完善的工具,但是也提供了一些基本的调试命令,其中对于graphics图形栈的调试,可以通过如下命令查看:

# 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

虽然不是很完备,但是凑合能用吗!希望OH以后能把相关的调试手段补全吗!聊胜于无!




写在最后

  • OH的buffer管理参照的是Android中的,并且是通过renderserver对buffer进行管理的,有点类似android 12以前的实现
  • ,但是并不是通过egl gbm进行buffer的申请和释放的,而是通过调用开源的Mesa实现将OH的surface传递到了Mesa中,然后在Mesa中通过surface的dequeue和queue将绘制好的buffer传递回去
  • 而OH的buffer的最终申请调用到了/device/soc/phytium/d2000/hardware/display/display_gralloc模块中
  • buffer的申请不一定需要通过render_server进行中转,可以是native应用可以创建ConsumerSurface,然后获取produceSurace,绕过和render_server交互,直接和gralloc服务进行交互
  • buffer的mmap不是通过gralloc服务进行的,而是通过render_service进行的

这里我们也可以参考,OH官网的一个例子简单来说明,gralloc buffer的基本流程:

  • 以WMS组件和UI组件交互为例,UI为生产者,WMS为消费者。
  • 生产者:从Free队列中获取Buffer,将UI内容绘制到Buffer中,然后将Buffer放到Dirty队列;
  • 消费者:从Dirty队列中获取Buffer并进行合成,然后将Buffer重新放到Free队列中。

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/507257.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

玩机搞机--定制系统 隐藏app桌面图标 反编译app【二】

在定制rom的过程中。客户要求内置某些app。个别需求内置的app不能显示在桌面&#xff0c;那么对应的内置app方法就不做细阐述。可以参考原固件操作 那么今天主要讲下隐藏app的操作解析 &#x1f494;&#x1f494;&#x1f494;&#x1f494;&#x1f494;&#x1f494;&#…

C++知识点 -- C++的类型转换

C知识点 – C的类型转换 文章目录 C知识点 -- C的类型转换一、C语言中的类型转换二、C的强制类型转换1.static_cast2.reinterpret_cast3.const_cast4.dynamic_cast 一、C语言中的类型转换 void test() {int i 0;//隐式类型转换&#xff08;意义相近的类型&#xff09;double …

只下载rpm包而不安装(用于内网虚拟机使用)

这里写目录标题 问题&#xff1a;解决&#xff1a;1. 安装yum-utils2. 下载rpm包3. 将rpm包拷贝到离线的虚拟机并安装 问题&#xff1a; 公司虚拟机仅使用内网无法通过yum下载依赖&#xff1b; 解决方法之一就是从一台连了公网的虚拟机(NAT) 下载需要的rpm包&#xff0c;然后…

Xcode安装与配置

安装Xcode Xcode需要macOS系统上安装&#xff0c;截止到2020年1月31日&#xff0c;最新版本为11.3.1。你可以选择在苹果开发者网站下载Xcode安装文件或去苹果应用市场安装&#xff0c;无论哪种方式安装Xcode&#xff0c;都需要有一个自己的Apple ID&#xff0c;具体的申请注册流…

unittest 测试框架的使用

文章目录 1. unittest 框架解析2. 批量执行测试脚本1&#xff09;构建测试套件addTest() 方法makeSuite() 方法TestLoader() 方法 2&#xff09;用例的执行顺序3&#xff09;忽略测试用例的执行 3. unittest 断言4. HTML 报告生成5. 异常捕获与错误截图6. 数据驱动1&#xff09…

【项目测试报告】网页版博客系统 + online 好友聊天室

网页版博客系统 online 好友聊天室&#xff08;项目介绍&#xff09; 实现一个网页版的博客系统&#xff0c;提供了一个技术文章论坛&#xff0c;同时也提供了用户之间在线交流的平台。 网页博客系统支持以下核心功能&#xff1a; 用户注册、登录、注销功能&#xff08;登录…

JAVAWeb11-服务器渲染技术 -JSP-02-EL表达式(会使用)

1. EL 表达式介绍 EL 表达式全称&#xff1a;Expression Language&#xff0c;是表达式语言EL 表达式主要是代替 jsp 页面的表达式脚本<%request.getAttribute("xx")%>EL 表达式输出数据时&#xff0c;比 jsp 的表达式脚本简洁EL 表达式基本语法&#xff1a; …

HAL库版FreeRTOS(下)

目录 FreeRTOS 事件标志组FreeRTOS 事件标志组简介FreeRTOS 事件标志组相关API 函数FreeRTOS 事件标志组实验功能设计软件设计下载验证 FreeRTOS 任务通知FreeRTOS 任务通知简介任务通知的优势任务通知的缺点 FreeRTOS 任务通知相关API 函数 FreeRTOS 事件标志组 事件标志组与…

【Leetcode】241. 为运算表达式设计优先级

241. 为运算表达式设计优先级&#xff08;中等&#xff09; 解法一&#xff1a;分治法 对于这道题&#xff0c;加括号其实就是决定运算次序&#xff0c;所以我们可以把加括号转化为&#xff0c;「对于每个运算符号&#xff0c;先执行处理两侧的数学表达式&#xff0c;再处理此…

提高APP安全性的必备加固手段——深度解析代码混淆技术

APP 加固方式 Android APP 加固是优化 APK 安全性的一种方法&#xff0c;常见的加固方式有混淆代码、加壳、数据加密、动态加载等。下面介绍一下 Android APP 加固的具体实现方式。 混淆代码&#xff1a; 使用 ProGuard 工具可以对代码进行混淆&#xff0c;使得反编译出来的代…

makefile语法解析

gcc语法简介 gcc (-c) hello.c world.c -o main-c表示只编译不链接 -o目标文件 此外&#xff0c;还有-I&#xff08;大写的I&#xff09;表示给gcc添加自定义的头文件的路径 -L表示给gcc添加额外的搜索库的路径 -g选项的意义是“生成调试信息&#xff0c;该程序可以被调试器调…

【Java入门合集】第五章抽象类和接口(二)

博主&#xff1a;命运之光 专栏&#xff1a;JAVA入门 学习目标 1.了解什么是抽象类&#xff0c;什么是接口&#xff1b; 2.掌握抽象类和接口的定义方法&#xff1b; 3.理解接口和抽象类的使用场景&#xff1b; 4.掌握多态的含义和用法&#xff1b; 5.掌握内部类的定义方法和使用…

【Hive实战】Hive元数据存储库数据增多的分析

Hive元数据存储库数据增多的分析 2023年5月8日 文章目录 Hive元数据存储库数据增多的分析问题新增Hive相关的DDL操作创建Hive库库授权到用户 创建Hive表 内部表非分区表表授权到用户一级分区表二级分区表分桶表分桶排序表 查询指令核心表分析表关系图表以库表为主以hive表为主以…

人人都可用的ChatGPT,Edge浏览器-免费ChatGPT保姆级教程!非常详细!

人工智能大浪潮已经来临&#xff0c;对于ChatGPT&#xff0c;我觉得任何一个玩互联网的人&#xff0c;都应该重视起来&#xff0c;用起来。但是国内使用需要解决科学上网、注册、收费等繁琐问题。 所以&#xff0c;今天这篇文章就来推荐一个插件&#xff0c;无需任何繁琐操作&…

第一次省赛团队训练 - BAPC 2022 Pre(DAPC 2022)

B (2). Bubble-bubble Sort [ 提交记录 ] [ 问题 3462 ] 时间限制: 2000MS 空间限制: 256MB 结果评判: 文本对比 正确/提交: 7 (5) / 15 官方标签: 用户标记: 题目描述 Bubbles! As a fanatical supporter of the Bubbles Are Perfect Creatures movement, you have ac…

第8章 未执行缓存的强制清理操作导致显示异常解决方案

1 异常产生原因&#xff1a; 由于未为Role实体定义相就的缓存强制销毁器类&#xff1a;Services.Customers.Caching.RoleCacheEventConsumer,从而导致Services.Events.EventPublisher.PublishAsync<TEvent>(TEvent event)中的 consumers实例为0,如下图所示&#xff1a; 2…

深入理解移动端布局:Viewport与设备像素比

在移动端开发中&#xff0c;了解和掌握不同设备的布局特点是非常重要的。本文将介绍两个关键概念&#xff1a;Viewport 和设备像素比&#xff08;DPR&#xff09;&#xff0c;帮助你更好地理解移动端布局。 一、什么是 Viewport&#xff1f; Viewport 是用户在浏览器中可见的网…

JS知识点(包括原型,原型对象,数据类型,数据类型的检测)

目录 1、JavaScript有哪些数据类型&#xff0c;它们的区别&#xff1f; 2、基本数据类型和引用数据类型地区别&#xff1a; 3、数据类型检测的方式有哪些: 4、判断数组的方式有那些&#xff1f; 5、null和undefined区别&#xff1a; 6、为什么typeOf null得到object而不是n…

22个提升生产力的工具推荐,稳了

子曰&#xff1a;工欲善其事&#xff0c;必先利其器。 本文给大家推荐22个提高生产力的工具&#xff0c;总有一款符合你的需求。&#x1f604;&#x1f604;&#x1f604; 提高生产效率工具推荐 滴答清单/Todoist文件检索利器&#xff1a;Everything文件管理软件-Allen Explor…

基于SpringBoot的大学生租房系统

背景 大学生租房系统设计的目的是建立一个高效的平台&#xff0c;采用简洁高效的Java语言与Mysql数据库等技术&#xff0c;设计和开发了本大学生租房系统设计。该系统主要实现了用户和房主通过系统注册用户&#xff0c;登录系统后能够编辑自己的个人信息、查看首页&#xff0c…