Android Qcom Display学习(十二)

news2025/1/13 17:31:28

该系列文章总目录链接与各部分简介: Android Qcom Display学习(零)
本章主要是基于高通平台上dump出GPU渲染 or GPU合成 or HWC合成的GraphicBuffer的数据。

起初是在B站上看到这么一个视频,能dump出每个Layer的数据显示系统原理以及图形系统调试,看到Android Framework中自带了
Layer::dump的方法,但是在Android S上并没有,在Google的历史中找到移植时发现Android版本的更替Layer.cpp中的改动很大
https://android.googlesource.com/platform/frameworks/native/+/e64a79c/services/surfaceflinger/Layer.cpp
https://android.googlesource.com/platform/frameworks/native/+/e64a79c/services/surfaceflinger/SurfaceFlinger.cpp

于是自己写了个dump的方法,结果发现在Layer.cpp中通过getBuffer()拿到的数据一直是空的,又想通过layerSettings.source.buffer.buffer来获取GraphicBuffer,最终找到了frameworks/native/libs/renderengine/skia/SkiaGLRenderEngine.cppSkiaGLRenderEngine::drawLayers

static void dumpBuffer(void* addr, uint32_t w, uint32_t h, uint32_t s, PixelFormat f){
    if( !addr){
        ALOGE("Addr is NULL");
        return;
    }

    static int count = 0;
    char filename[100];
    memset(filename, 0, sizeof(filename));
    sprintf(filename, "/data/dump/layer_gpu_%d_frame_%d_%d_%d.rgb", count, w, h, f);
    ALOGD("dump GraphicBUffer to RGB file:%s",filename);

    count ++;
    int fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0664);
    if(fd < 0) return;
    void* base = addr;
    //uint32_t c= dataSpaceToInt(d);
    //write(fd, &w, 4);
    //write(fd, &h, 4);
    //write(fd, &f, 4);
    //write(fd, &c, 4);
    size_t Bpp = bytesPerPixel(f);
    for (size_t y = 0; y < h; y++) {
        write(fd, base, w*Bpp);
        base = (void *)((char *)base + s*Bpp);
    }
   close(fd);
}

static void dumpLayers(const sp<GraphicBuffer>& target){
    void *addr = NULL;

    uint32_t w, s, h, f;
    w = target->getWidth();
    h = target->getHeight();
    s = target->getStride();
    f = target->getPixelFormat();

    int result = target->lock(GraphicBuffer::USAGE_SW_READ_OFTEN, &addr);
    if(result < 0){
        ALOGE("lock buffer failed: %d", result);
    }
    dumpBuffer(addr, w, h, s, f);
}

拿到dump出的GraphicBuffer在7YUV和YUVIEW上发现只有星点都不是正常画面,在RenderSurface::queueBuffer中dump GPU合成Layers的GraphicBuffer,发现也是星点,当然这个也是预料之中,Layers的数据都不对合成后的肯定也有问题,
看了这个大佬的博客 Android 图像显示系统 - 导出图层数据的方法介绍(dump GraphicBuffer raw data)

static void dumpGraphicRawData2file(const native_handle_t* bufferHandle,
                                    uint32_t width, uint32_t height,
                                    uint32_t stride, int32_t format)
{
    ALOGE("%s [%d]", __FUNCTION__, __LINE__);

    static int sDumpCount = 0;

    if(bufferHandle != nullptr) {
        int shareFd = bufferHandle->data[0];
        unsigned char *srcAddr = NULL;
        uint32_t buffer_size = stride * height * bytesPerPixel(format);
        srcAddr = (unsigned char *)mmap(NULL, buffer_size, PROT_READ, MAP_SHARED, shareFd, 0);

        char filename[100];
        memset(filename, 0, sizeof(filename));
        sprintf(filename, "data/dump/layers_gpu_composer_%d_frame_%d_%d_%d.raw", sDumpCount, width, height, format);

        int dumpFd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0644);

        if(dumpFd >= 0 && srcAddr != NULL) {
            ALOGE("jerry dumpFd success");
            write(dumpFd, srcAddr, buffer_size);
            close(dumpFd);
        }
        munmap((void*)srcAddr, buffer_size);
    }
}

网上搜了一大堆,才知道合成方式有GPU和HWC,可通过adb shell dumpsys SurfaceFlinger > SurfaceFlinger.txt

6 Layers
  - Output Layer 0xb400007758f7fa30(Wallpaper BBQ wrapper#0)
        hwc: layer=0x088 composition=DEVICE (2) 
  - Output Layer 0xb400007758f97b00(com.android.launcher3/com.android.searchlauncher.SearchLauncher#0)
        hwc: layer=0x089 composition=DEVICE (2) 
  - Output Layer 0xb400007758f8a620(StatusBar#0)
        hwc: layer=0x087 composition=CLIENT (1) 
  - Output Layer 0xb400007758f87500(NavigationBar0#0)
        hwc: layer=0x08a composition=CLIENT (1) 
  - Output Layer 0xb400007758f9a3f0(ScreenDecorOverlay#0)
        hwc: layer=0x085 composition=CLIENT (1) 
  - Output Layer 0xb400007758f72550(ScreenDecorOverlayBottom#0)
        hwc: layer=0x084 composition=CLIENT (1) 

BufferStateLayer::setBuffer中添加dump HWC中的GraphicBuffer,发现还是不正常的,后来在高通文档里发现高通本来就有dump Layers的方法,于是就想看看有没有问题

adb root
adb shell setprop vendor.gralloc.disable_ubwc 1
adb shell setprop vendor.gralloc.enable_fb_ubwc 0
adb shell stop vendor.gralloc-2-0
adb shell start vendor.gralloc-2-0
adb shell stop vendor.qti.hardware.display.allocator
adb shell start vendor.qti.hardware.display.allocator
stop;start // Reboot Android frame to make the change effective
adb shell dumpsys SurfaceFlinger 
adb shell setenforce 0

GPU
adb root
adb shell "vndservice call display.qservice 21 i32 2 i32 1 i32 3"
adb pull /data/vendor/display/frame_dump_disp_id_00_builtin/ ./

结果结果发现图像是正常的,然后dump我们自己的GraphicBuffer数据,发现也正常了,右边是GPU合成的Layer(StaturBar和NavigationBar0等),左边是非GPU合成的Layer图(Launcher),最终得出跟ubwc有关,ubwc说是高通私有的一个格式,所以可能造成图像无法正常查看问题。
在这里插入图片描述
最后总结一下部分送显的流程,说明以下上述dump的添加位置,图片来自于Android 12(S) 图像显示系统 - GraphicBuffer同步机制 - Fence
在这里插入图片描述

VSYNC -> onMessageRefresh -> CompositionEngine::present -> Output::present

(1) writeCompositionState -> writeStateToHWC -> writeOutputIndependentPerFrameStateToHWC -> writeBufferStateToHWC->
		 Layer::setBuffer -> Composer::setLayerBuffer
	合成方式Composition::CLIENT会被Ingored, Device的合成会直接送入HWC	

(2) setColorTransform 
    设置颜色矩阵作用于所有layer, Night Light对应护眼模式, Andorid自带模式
	
(2) prepareFrame -> chooseCompositionStrategy 
    将合成类型是Client还是Device送入FrameBufferSurface, 默认是Client GPU合成
	
(3) finishFrame -> composeSurfaces -> SkiaGLRenderEngine::drawLayers -> RenderSurface::queueBuffer -> 
	    advanceFrame -> RenderSurface::nextBuffer -> setClientTarget
	drawLayers中会判断hasClientComposition,说明是GPU合成,rendyFence同步判断准备好后queueBuffer放入BufferQueue,
	FrameBufferSurface::nextBuffer从BufferQueue中取出后通过setClientTarget送入HWC中

Android 12(S) 图像显示系统 - GraphicBuffer同步机制 - Fence
Android图像首先由CPU将对象处理为多维图像、纹理(Bitmaps,Drawables一起打包到统一的Texture纹理中),然后再传递给GPU,由于CPU和GPU两个硬件是异步的,CPU调用OpenGL等命令时,是由GPU去执行真正的绘图操作,绘图何时结束,CPU时不清楚的,除非等待这些命令完成,因此需要引入Fence同步机制。
    Fence的要旨是控制GraphicBuffer的状态,是否允许工作的资源竞争问题。GraphicBuffer相对应的BufferState状态一定程度上说明了该GraphicBuffer的归属,但只指示了CPU里的状态,而GraphicBuffer的真正使用者一般是GPU。比如当生产者把一个GraphicBuffer放入BufferQueue时,只是在CPU层面完成了归属的转移。但GPU说不定还在用,如果还在用的话消费者是不能拿去合成的。这时候GraphicBuffer和生产消费者的关系就比较暧昧了,消费者对GraphicBuffer具有拥有权,但无使用权,它需要等一个信号,告诉它GPU用完了,消费者才真正拥有使用权。
    VSync的要旨是协调硬件和软件之间的工作时序,屏幕的刷新帧率是固定的,因此每规定时间都需要准备好下一帧,如果准备好则会造成画面延迟,一帧显示多次,如果准备过快,则会造成画面撕裂,显示多帧,Vsync信号就是用来控制前后缓冲区切换的节奏(也即是DRM中的PageFlip切换机制)

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

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

相关文章

Delphi 中 FireDAC 数据库连接(设置选项)

描述了为什么选项集使FireDAC成为一个灵活的数据库框架以及如何使用这些选项。FireDAC提供了大量的选项&#xff0c;这些选项被组织成一个分层的选项系统,大多数选项可以保留其默认值。一、议题TopicDescription数据类型映射FireDAC提供了一个灵活的可调整的数据类型映射系统&a…

command-line变成-bash-4.2

故障描述&#xff1a; 故障诊断&#xff1a; 分析用户创建的过程&#xff1a; Useradd jfedu1命令默认创建用户jfedu1&#xff0c;会根据如下步骤进行操作&#xff1a; 读取/etc/default/useradd&#xff0c;根据配置文件执行创建操作&#xff1b; 在/etc/passwd文件中添加…

Python 之 Pandas merge() 函数、set_index() 函数、drop_duplicates() 函数和 tolist() 函数

文章目录一、merge() 函数1. inner2. left 和 right3. outer二、set_index() 函数三、drop_duplicates() 函数四、tolist() 函数五、视频数据分析案例1. 问题要求2. 解决过程在最开始&#xff0c;我们先导入常规的 numpy 和 pandas 库。 import numpy as np import pandas as …

【数据挖掘】2、数据预处理

文章目录一、数据预处理的意义1.1 缺失数据1.1.1 原因1.1.2 方案1.1.3 离群点分析1.2 重复数据1.2.1 原因1.2.2 去重的方案1.3 数据转换1.4 数据描述二、数据预处理方法2.1 特征选择 Feature Selection2.2 特征提取 Feature Extraction2.2.1 PCA 主成分分析2.2.2 LDA 线性判别分…

四维地球2.0上线,中国四维遥感云平台布局初见端倪

‍数据智能产业创新服务媒体——聚焦数智 改变商业近日&#xff0c;土耳其大地震一直备受全球各国人民的关注&#xff0c;为了在黄金72小时内帮助解救受困人员&#xff0c;包括中国在内的不少国家纷纷向土耳其政府和人民伸出援手&#xff0c;除了派出专业的救援队伍之外&#…

数据结构前提知识

数据结构数据结构 个体的存储个体关系的存储算法对存储数据的操作程序数据结构算法衡量算法的标准时间复杂度&#xff1a;注意不是程序执行的时间&#xff0c;因为一个程序执行的时间取决于软硬件环境&#xff0c;不同的机器&#xff0c;执行的速度不一样&#xff0c;配置好的…

【Unity】P2 基础操作

Unity基础操作移动、旋转与缩放移动方法一&#xff1a;xyz移动方法二&#xff1a;平面移动方法三&#xff1a;直接调整xyz的position三值进行调整旋转方法一&#xff1a;选择旋转按键并旋转方法二&#xff1a;按住CTRL再进行旋转操作&#xff0c;每次15度方法三&#xff1a;通过…

工作中单例模式用法及其使用场景?

前言 最近工作中有这么一个需求&#xff0c;我们系统出单后&#xff0c;需要同步数据到合作方&#xff0c;合作方对数据接收并解析反馈结果文件给我们&#xff0c;根据结果文件状态判断合作方系统是否解析成功&#xff0c;对于失败的单子&#xff0c;需要邮件通知相关负责人。…

微服务实战02-EurekaServer注册中心

EurekaServer &#xff0c;它扮演的角色是注册中心&#xff0c;用于注册各种微服务&#xff0c;以便于其他微服务找到和访问。 1、Eureka是什么 Eureka是Netflix的一个子模块&#xff0c;也是核心模块之一。Eureka是一个基于REST的服务&#xff0c;用于定位服务&#xff0c;以…

AUTOSAR为啥要开发新的社区商业模式?

总目录链接>> AutoSAR入门和实战系列总目录 文章目录1 自适应平台架构中的集群更新1.1 ara::diag 服务&#xff08;诊断&#xff09;更新1.2 信号到服务映射和自动驾驶接口让我们讨论一下信号到服务映射服务:Automated Driving Interface:2 车载应用商店概念本文介绍Re…

【RabbitMQ笔记09】消息队列RabbitMQ之常见方法的使用

这篇文章&#xff0c;主要介绍消息队列RabbitMQ之常见方法的使用。 目录 一、消息队列常见方法 1.1、连接工厂ConnectionFactory 1.2、连接Connection 1.3、通道Channel 1.4、交换机相关方法 &#xff08;1&#xff09;exchangeDeclare()声明交换机 1.5、队列相关方法 …

算法训练营 day58 动态规划 判断子序列 不同的子序列

算法训练营 day58 动态规划 判断子序列 不同的子序列 判断子序列 392. 判断子序列 - 力扣&#xff08;LeetCode&#xff09; 给定字符串 s 和 t &#xff0c;判断 s 是否为 t 的子序列。 字符串的一个子序列是原始字符串删除一些&#xff08;也可以不删除&#xff09;字符而…

03、SVN 建立版本库

SVN 建立版本库1 版本库2 版本库的建立步骤2.1 创建版本库的根目录2.2 创建子目录2.3 通过命令创建版本库2.4 生成目的介绍1 版本库 Subversion 是将文件数据信息保存到版本库中进行管理的Subversion 允许用户对版本库目录进行定制 2 版本库的建立步骤 2.1 创建版本库的根目…

引用数据类型和基本数据类型

1.基本数据类型&#xff1a; byte&#xff1a;字节类型&#xff0c;Java中最小的数据类型&#xff0c;1个字节&#xff0c;取值范围-128~127&#xff0c;默认值0 char&#xff1a;字符型&#xff0c;用于存储单个字符&#xff0c;2个字节&#xff0c;取值范围0~65535&#xf…

Redis使用,AOF、RDB

前言 如果有人问你&#xff1a;"你会把 Redis 用在什么业务场景下&#xff1f;" 我想你大概率会说&#xff1a;"我会把它当作缓存使用&#xff0c;因为它把后端数据库中的数据存储在内存中&#xff0c;然后直接从内存中读取数据&#xff0c;响应速度会非常快。…

“速通“ 老生常谈的HashMap [实现原理源码解读]

&#x1f473;我亲爱的各位大佬们好&#x1f618;&#x1f618;&#x1f618; ♨️本篇文章记录的为 HashMap 实现原理&&源码解读 相关内容&#xff0c;适合在学Java的小白,帮助新手快速上手,也适合复习中&#xff0c;面试中的大佬&#x1f649;&#x1f649;&#x1f…

RocketMQ动态增加NameServer

前言 通过HTTP服务来设置NameServer地址&#xff0c;是唯一支持动态增加NameServer的方式&#xff0c;无需重启其它组件 网上搜了下没看到有兄弟们演示这块&#xff0c;所以刚才自己试了试&#xff0c;做个笔记 本文有详细的演示过程 都知道NameServer有4种配置方式&#xff0…

simulink入门指南

系列文章目录 文章目录系列文章目录常用操作技巧项目练习 - 动态系统二阶系统建模比例积分控制燕子俯冲系统建模滤波位操作总结常用操作技巧 画面缩放 空格键 鼠标左键: 拖拽空格键: fit屏幕 信号操作 双击signal可添加标签, 鼠标右键拖拽可给信号添加分支同一分支上的sig…

【并发基础】线程,进程,协程的详细解释

目录 一、什么是进程和线程 1.1 进程是什么呢&#xff1f; 1.2 线程又是什么呢&#xff1f; 1.3 线程和进程之间的关系 操作系统、进程、线程之间的关系图&#xff1a; 进程与线程的模型图&#xff1a; 下面来思考这样一个问题&#xff1a;为什么程序计数器、虚拟机栈和本地方法…

QNX7.1 交叉编译开源库

1.下载QNX7.1 SDK并解压 ITL:~/work/tiqnx710$ ls -l 总用量 16 drwxrwxr-x 4 xxx4096 1月 28 13:38 host -rwxrwxr-x 1 xxx 972 1月 28 13:38 qnxsdp-env.bat -rwxrwxr-x 1 xxx 1676 1月 28 13:38 qnxsdp-env.sh drwxrwxr-x 3 xxx 4096 1月 28 13:38 target xxxITL:~/work/ti…