文章目录
-
- [Android 图形库体系回顾](#Android 图形库体系回顾)
- 1、图形库使用
-
- [1)OPENGL ES 在Android的使用场景分析](#1)OPENGL ES 在Android的使用场景分析)
- 2)Android-Opengl学习专栏
- 3)资料快车
- 2、mesa3d概述
- 3、mesa3d框架介绍
- [4、shading Language](#4、shading Language)
- 5、使用Mesa画一个静态彩色三角形案例
Android 图形库体系回顾

为什么找不到Mesa3d,OpenGL-ES的开源实现就是Mesa3d,对于图形库,我们把握框架即可
1、图形库使用
1)OPENGL ES 在Android的使用场景分析
OPENGL ES 在Android的使用,以转场动画为例 : https://juejin.cn/post/7472770757073649700
2)Android-Opengl学习专栏
https://juejin.cn/column/7140455108407459854
3)资料快车
1)mesa & gullium3D介绍:https://juejin.cn/post/6844903841096269837
2)mesa源码目录介绍:https://zhaogang.blog.csdn.net/article/details/144786046
3)mesa框架与目录:https://winddoing.github.io/post/39ae47e2.html
4)Linux GPU系列-05-MESA架构 :http://joyxu.github.io/2021/05/13/gpu05/
2、mesa3d概述
1、mesa是一个免费的图形栈,支持多种GL(openGL、Vulkan) 和 平台(Linux、windows、mac),MESA同时实现了Vulkan、OpenGL、OpenGL ES、OpenCL、EGL、WGL、VA、VDPAU等规范,源码目录非常庞大杂乱,实现也十分复杂;
2、mesa的作用(本身就是OpenGL ES 、EGL的实现)
1)对接各种GPU硬件,将应用层对GL API的调用转换到对硬件GPU的调用上;
2)各种 GL API 的纯软实现,当没有可用的硬件时,它可以提供传软件的 GL API 的实现
3、传统mesa直接转换GL访问驱动,因此厂商需要适配每一种GL和不同平台下的GPU driver,复用低效导致工作量较大,gullium3D解决此问题,移植新平台只需适配较少代码,gullium3D当然也是我们重点学习分析对象;
3、mesa3d框架介绍
1)MESA现代框架

1)分为经典架构(Mesa Classics) 和 Gallium架构,不同应用依赖不同的架构;
2)对接GPU搭配libdrm使用;
2)Gallium架构

7、源码介绍(基于Gallium3D架构):
/android/external/mesa3d/src/gallium/drivers/panfrost/pan_job.c
1、Auxiliary
存放公共函数或辅助的服务,比如状态缓存和缓存管理
src/gallium/auxiliary
2、State Tracker
把上层库的state(blend modes \ texture state)和draw command (glDrawArrays\glDrawPixels)等转换mesa内部pipe对象和操作
src/mesa/state_tracker/
3、frontend
前端接口是与上层图形API(OpenGL\Vulkan\Direct3D)交互的部分,前端驱动接口、命令缓冲区接口、api转换层、上下文管理、资源和状态管理
src/gallium/frontend/dri
4、pipe Driver
把Gallium的state、shader和primitive概念转换成硬件能懂的语言
src/gallium/drivers/panfrost
5、Winsys
实例化state tracker和pipe driver,并和具体的操作系统及2D显示器驱动绑定
src/gallium/winsys/panfrost
创建screen流程
/android/external/mesa3d/src/gallium/auxiliary/target-helpers/drm_helper.h
pipe_panfrost_create_screen(int fd, const struct pipe_screen_config *config)
--panfrost_drm_screen_create(fd);
----panfrost_create_screen()
/android/external/mesa3d/src/gallium/drivers/panfrost/pan_screen.c
------panfrost_create_screen(int fd, struct renderonly *ro)
--------panfrost_open_device(screen, fd, dev);
/android/external/mesa3d/src/panfrost/lib/pan_props.c
----------panfrost_bo_create(dev, ...)
两个重要概念
1)CSO context:创建、销毁、管理GPU状态中不变的变量
2)Draw :有些GPU硬件不支持坐标变化、光照、裁剪,Gallium提供的软件实现
MESA调用流程
state tracker -> CSO context -> Draw(硬件则不需要) -> Pipe Driver -> Winsys -> 具体的OS -> OS内核态GPU驱动 -> 具体的GPU硬件
其中
state tracker和pipe driver通信是通过pipe context 和pipe screen
state tracker也可以直接通过p_winsys和Winsys通信
厂家主要实现哪些?两部分
src/gallium/drivers/panfrost
src/gallium/winsys/panfrost
实现winsys可以参考纯软件实现的kms_dri_sw_winsys.c
mesa生成物
libEGL.so //EGL动态库
libglapi.so //这是一个共享GLAPI库,用于提供OpenGL API调用的间接层;
4、shading Language
SL : shading Language,着色器语言
1、着色是一个图形领域的专业术语,在白纸上着色 描绘各种颜色,说白一点就是画图的意思,处理单位:
1)顶点着色器 - 处理单位是顶点,并裁剪空间坐标
2)片段着色器 - 处理单位是区域
2、光栅化,将图元转化为像素数据;
3、纹理:比如 将图片数据放在某个绘制的图形区域 就叫纹理;
4、
为什么在用户态,而不是驱动?可以理解为OpenGL等图形库的特殊表达式罢了
为什么不使用编程语言?当编程语言较难满足,有必要使用新的方式!
从而达到效果:尽可能控制渲染过程,同时利用图形硬件的并行性,提高算法效率
着色器编程语言,用于在GPU上执行图形渲染管线中的可编程阶段,图形编程的核心语言,GPU本身也是一个处理器,可以运行程序,而着色器语言编写的程序会被GL转化为特定的数据结构,再让驱动提交给GPU进行处理;
5、Shader Language目前主流是GLSL和HLSL:
基于 OpenGL 的 OpenGL Shading Language,简称 GLSL; - 类C语言,嵌入式场景
基于 DirectX 的 High Level Shading Language,简称 HLSL; - windows
我们重点看GLSL
6、GLSL语法详解,从入门到实践
https://blog.csdn.net/2503_92624912/article/details/156241550
GLSL编译器源码:android/external/mesa3d/src/compiler/SConscript.glsl
7、着色器文件编译-链接-使用流程
https://www.cnblogs.com/icmzn/p/19417570
glsl -> 编译器 -> 代码片段 -> GL库初步处理 -> 驱动发送给GPU执行
8、使用GLSL编写一个纹理采用
uniform sampler2D ourTexture;
void main()
{
FragColor = texture(ourTexture, TexCoord);
}
9、SKSL
参考GLSL,在Android上skia图形引擎也有自己的Shader Language - SKSL,类C++语言
https://juejin.cn/post/7199933874305712189
1)sksl库
/android/external/skia/resources/sksl
2)使用SKSL,编写一个线性渐变着色器
uniform float2 linear_gradient_start;
uniform float2 linear_gradient_end;
uniform half4 linear_gradient_start_color;
uniform half4 linear_gradient_end_color;
half4 main(float2 p)
{
float t = saturate((p.y - linear_gradient_start.y) / (linear_gradient_end.y - linear_gradient_start.y));
return mix(linear_gradient_start_color, linear_gradient_end_color, t);
}`
5、使用Mesa画一个静态彩色三角形案例
1)谁来调用Mesa
1.CTS测试用例 - 应用层
/android/cts/tests/tests/opengl/src/android/opengl/cts/ByteBufferTest.java
2.Frameworks java层
/android/frameworks/base/opengl/java/android/opengl/*
3.JNI
/android/frameworks/base/opengl/java/com/google/android/gles_jni/*
4.native层 - Mesa
glBindTexture(GL_TEXTURE_2D, textureHandle);
1)GL api(用户态功能)
/android/external/mesa3d/include/GLES/gl.h
1.画三角形
glDrawArrays(GL_TRIANGLES, 0, 3);
2)代码实现
1.完整代码
https://github.com/LinuxMadGuy/opengl-misc/blob/master/OpenGL/triangle/triangle.cpp
2.重点代码
void main() {
float vertices[] = {
-0.5f, -0.5f, 0.0f, // left
0.5f, -0.5f, 0.0f, // right
0.0f, 0.5f, 0.0f // top
};
//1.GPU端生成一个顶点数组对象(VAO)和一个顶点缓冲对象(VBO),这是存放和管理顶点数据的基础。
unsigned int VBO, VAO;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
// bind the Vertex Array Object first, then bind and set vertex buffer(s), and then configure vertex attributes(s).
//绑定VAO
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); //准备Vertext数据
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
// render loop
// -----------
while (!glfwWindowShouldClose(window))
{
//2.render
glClearColor(0.2f, 0.3f, 0.3f, 1.0f); //设置清屏背景颜色
glClear(GL_COLOR_BUFFER_BIT);//开始清屏
// draw our first triangle
glUseProgram(shaderProgram);
glBindVertexArray(VAO); // seeing as we only have a single VAO there's no need to bind it every time, but we'll do so to keep things a bit more organized
glDrawArrays(GL_TRIANGLES, 0, 3); //开始GPU进行绘制三角形
//3.glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.)
glfwSwapBuffers(window); //交换前后帧缓存区
glfwPollEvents(); //处理IO事件
}
}
3.小结
准备好绘制数据(顶点数据、命令id等) -> GPU工作 -> 显示
1、准备Vertext数据
glBufferData
/android/external/mesa3d/src/mesa/main/bufferobj.c
mesa_BufferData()
--_mesa_buffer_data()
---buffer_data_error()
-----buffer_data()
------ctx->Driver.BufferData()
/android/external/mesa3d/src/mesa/state_tracker/st_cb_bufferobjects.c
--------st_bufferobj_data()
----------bufferobj_data()
/android/external/mesa3d/src/gallium/auxiliary/util/u_inlines.h
------------pipe_buffer_write()
--------------pctx->buffer_subdata()
/android/external/mesa3d/src/gallium/drivers/panfrost/pan_resource.c
----------------u_default_buffer_subdata()
------------------pipe->transfer_map() //各GPU厂商实现,panfrost使用MESA公共函数
/android/external/mesa3d/src/gallium/drivers/panfrost/pan_resource.c
pctx->buffer_subdata = u_default_buffer_subdata;
2、绘制
glDrawArrays
/android/external/mesa3d/src/mesa/main/draw.c
--_mesa_DrawArrays()
----_mesa_draw_arrays()
------gl_context.Driver.Draw()
/android/external/mesa3d/src/mesa/state_tracker/st_draw.c
--------st_draw_vbo()
/android/external/mesa3d/src/gallium/auxiliary/cso_cache/cso_context.c
----------cso_draw_vbo(st->cso_context, &info);
/android/external/mesa3d/src/gallium/auxiliary/util/u_vbuf.c
------------u_vbuf_draw_vbo(vbuf, info);
--------------pipe->draw_vbo(pipe, &new_info);
/android/external/mesa3d/src/gallium/drivers/panfrost/pan_context.c
----------------panfrost_draw_emit_vertext()
/android/external/mesa3d/src/gallium/drivers/panfrost/pan_context.c
------------------pan_emit_draw_descs(batch, &cfg, PIPE_SHADER_VERTEX);
3、切换Framebuffer
glfwSwapBuffers
main::_mesa_Flush
gl_context::Driver.Flush
state_tracker::st_glFlush
draw_do_flush
panfrost::panfrost_flush
panfrost::panfrost_batch_submit_jobs
panfrost::panfrost_batch_submit_ioctl
drm::drmIoctl(DRM_IOCTL_PANFROST_SUBMIT)
进入kernel panfrost驱动
/android/vendor/amlogic/common/kernel/common_5.4/drivers/gpu/drm/panfrost/panfrost_drv.c
panfrost_ioctl_submit
panfrost_job_push
drm_sched_entity_push_job
drm_sched_rq_add_entity
panfrost_job_run
panfrost_job_hw_submit
panfrost_job_write_affinity (设置job和core的亲和性)
job_write (写job manager寄存器)