Mesa软件框架以及重要数据结构分析

news2024/12/28 6:23:00

Mesa软件框架以及重要数据结构分析



引言

Mesa的实现比较复杂,其中还有许多的数据结构之间的关系逻辑还不是很清楚。感觉分析了又没有分析一样,这里我们再理一理!


1.1 Mesa下EGL/GL核心数据结构和层级关系

在这里插入图片描述

MESA的核心数据结构很多很复杂,上图列举了一些核心数据结构主要强调了它们的层次关系,即上层使用下层的抽象结构(比如 函数指针调用),下层为上次做具体的实现(比如具体的函数实现),虽然是C代码但设计理念基本上与C++的继承类似(这个也是C语言实现大型代码框架的核心)。

这里的核心主要是Mesa软件EGL/GL层级的递进调用。


1.2 Mesa下核心文件和核心结构体


在这里插入图片描述


先从核心的几个文件入手:

  • dri2.c:该文件主要定义了dri库函数的扩展的入口,和各种extensions的对接,通常会通过dlsym加载__driDriverGetExtensions_##drivername对应函数,然后通过函数指针匹配到对应的extensions进行赋值
//mesa/src/gallium/frontends/dri/dri2.c


/* The extension is modified during runtime if DRI_PRIME is detected */
static const __DRIimageExtension dri2ImageExtensionTempl = {
    .base = { __DRI_IMAGE, 18 },

    .createImageFromName          = dri2_create_image_from_name,
    .createImageFromRenderbuffer  = dri2_create_image_from_renderbuffer,
    .destroyImage                 = dri2_destroy_image,
    .createImage                  = dri2_create_image,
    .queryImage                   = dri2_query_image,
    .dupImage                     = dri2_dup_image,
    .validateUsage                = dri2_validate_usage,
    .createImageFromNames         = dri2_from_names,
    .fromPlanar                   = dri2_from_planar,
    .createImageFromTexture       = dri2_create_from_texture,
    .createImageFromFds           = NULL,
    .createImageFromDmaBufs       = NULL,
    .blitImage                    = dri2_blit_image,
    .getCapabilities              = dri2_get_capabilities,
    .mapImage                     = dri2_map_image,
    .unmapImage                   = dri2_unmap_image,
    .createImageWithModifiers     = NULL,
    .createImageFromDmaBufs2      = NULL,
    .createImageFromDmaBufs3      = NULL,
    .queryDmaBufFormats           = NULL,
    .queryDmaBufModifiers         = NULL,
    .queryDmaBufFormatModifierAttribs = NULL,
    .createImageFromRenderbuffer2 = dri2_create_image_from_renderbuffer2,
};

/*
 * Backend function init_screen.
 */

static const __DRIextension *dri_screen_extensions_base[] = {
   &driTexBufferExtension.base,
   &dri2FlushExtension.base,
   &dri2RendererQueryExtension.base,
   &dri2GalliumConfigQueryExtension.base,
   &dri2ThrottleExtension.base,
   &dri2FenceExtension.base,
   &dri2InteropExtension.base,
   &dri2NoErrorExtension.base,
   &driBlobExtension.base,
};

/**
 * DRI driver virtual function table.
 *
 * DRI versions differ in their implementation of init_screen and swap_buffers.
 */
const struct __DriverAPIRec galliumdrm_driver_api = {
   .InitScreen = dri2_init_screen,
   .DestroyScreen = dri_destroy_screen,
   .CreateContext = dri_create_context,
   .DestroyContext = dri_destroy_context,
   .CreateBuffer = dri2_create_buffer,
   .DestroyBuffer = dri_destroy_buffer,
   .MakeCurrent = dri_make_current,
   .UnbindContext = dri_unbind_context,

   .AllocateBuffer = dri2_allocate_buffer,
   .ReleaseBuffer  = dri2_release_buffer,
};

/**
 * DRI driver virtual function table.
 *
 * KMS/DRM version of the DriverAPI above sporting a different InitScreen
 * hook. The latter is used to explicitly initialise the kms_swrast driver
 * rather than selecting the approapriate driver as suggested by the loader.
 */
const struct __DriverAPIRec dri_kms_driver_api = {
   .InitScreen = dri_kms_init_screen,
   .DestroyScreen = dri_destroy_screen,
   .CreateContext = dri_create_context,
   .DestroyContext = dri_destroy_context,
   .CreateBuffer = dri2_create_buffer,
   .DestroyBuffer = dri_destroy_buffer,
   .MakeCurrent = dri_make_current,
   .UnbindContext = dri_unbind_context,

   .AllocateBuffer = dri2_allocate_buffer,
   .ReleaseBuffer  = dri2_release_buffer,
};


/* This is the table of extensions that the loader will dlsym() for. */
const __DRIextension *galliumdrm_driver_extensions[] = {
    &driCoreExtension.base,// 它的实现在dri_util.c,并且它会被target.c调用到 
    &driImageDriverExtension.base,
    &driDRI2Extension.base,
    &gallium_config_options.base,
    NULL
};


  • target.c:这个文件我们要怎么描述它的相关功能呢,我们可以理解它为dri库函数库入口,我们会在dri_load_driver函数中通过dri_open_driver打开对应的so库,然后通过dlsym加载__driDriverGetExtensions_##drivername函数,然后通过dri_bind_extensions获取对应的扩展!
//mesa/src/gallium/targets/dri/target.c

//非常重要的一个宏定义
#define DEFINE_LOADER_DRM_ENTRYPOINT(drivername)                          \
const __DRIextension **__driDriverGetExtensions_##drivername(void);       \
PUBLIC const __DRIextension **__driDriverGetExtensions_##drivername(void) \
{                                                                         \
   globalDriverAPI = &galliumdrm_driver_api;                              \
   return galliumdrm_driver_extensions;                                   \
}


#if defined(HAVE_LIBDRM)

const __DRIextension **__driDriverGetExtensions_kms_swrast(void);//kms_swrast

PUBLIC const __DRIextension **__driDriverGetExtensions_kms_swrast(void)
{
   LOGE("__driDriverGetExtensions_kms_swrast");
   globalDriverAPI = &dri_kms_driver_api;//它的实现被定义在dri2.c中
   return galliumdrm_driver_extensions;//它的实现被定义在Dri2.cz中
}

#endif

//intel I915定义
#if defined(GALLIUM_I915)
DEFINE_LOADER_DRM_ENTRYPOINT(i915)
#endif

//AMD显卡dri函数入口定义
#if defined(GALLIUM_R300)
DEFINE_LOADER_DRM_ENTRYPOINT(r300)
#endif

#if defined(GALLIUM_R600)
DEFINE_LOADER_DRM_ENTRYPOINT(r600)
#endif


  • dri_util.c:它是dri2框架中的一个工具类,它内部实现的函数基本是前面dri2.c中扩展extensions的实现
//mesa/src/mesa/drivers/dri/common/dri_util.c

/**
 * \file dri_util.c
 * DRI utility functions.
 *
 * This module acts as glue between GLX and the actual hardware driver.  A DRI
 * driver doesn't really \e have to use any of this - it's optional.  But, some
 * useful stuff is done here that otherwise would have to be duplicated in most
 * drivers.
 * 
 * Basically, these utility functions take care of some of the dirty details of
 * screen initialization, context creation, context binding, DRM setup, etc.
 *
 * These functions are compiled into each DRI driver so libGL.so knows nothing
 * about them.
 * DRI实用功能
 * 此模块充当GLX和实际硬件驱动程序之间的粘合剂。DRI驱动程序实际上并不需要使用这些——它是可选的。
 * 但是,这里完成了一些有用的东西,否则将不得不在大多数驱动程序中重复。*基本上,这些实用程序函数负责屏幕初始化,上下文创建,上下文绑定,DRM设置等一些肮脏的细节。
 * 这些函数被编译到每个DRI驱动程序中,所以libGL。所以对他们一无所知。
 */
 


/** Core interface */
const __DRIcoreExtension driCoreExtension = {
    .base = { __DRI_CORE, 2 },

    .createNewScreen            = NULL,
    .destroyScreen              = driDestroyScreen,
    .getExtensions              = driGetExtensions,
    .getConfigAttrib            = driGetConfigAttrib,
    .indexConfigAttrib          = driIndexConfigAttrib,
    .createNewDrawable          = NULL,
    .destroyDrawable            = driDestroyDrawable,
    .swapBuffers                = driSwapBuffers, /* swrast */
    .createNewContext           = driCreateNewContext, /* swrast */
    .copyContext                = driCopyContext,
    .destroyContext             = driDestroyContext,
    .bindContext                = driBindContext,
    .unbindContext              = driUnbindContext
};

/** DRI2 interface */
const __DRIdri2Extension driDRI2Extension = {
    .base = { __DRI_DRI2, 4 },

    .createNewScreen            = dri2CreateNewScreen,
    .createNewDrawable          = driCreateNewDrawable,
    .createNewContext           = driCreateNewContext,
    .getAPIMask                 = driGetAPIMask,
    .createNewContextForAPI     = driCreateNewContextForAPI,
    .allocateBuffer             = dri2AllocateBuffer,
    .releaseBuffer              = dri2ReleaseBuffer,
    .createContextAttribs       = driCreateContextAttribs,
    .createNewScreen2           = driCreateNewScreen2,
};

const __DRIswrastExtension driSWRastExtension = {
    .base = { __DRI_SWRAST, 4 },

    .createNewScreen            = driSWRastCreateNewScreen,
    .createNewDrawable          = driCreateNewDrawable,
    .createNewContextForAPI     = driCreateNewContextForAPI,
    .createContextAttribs       = driCreateContextAttribs,
    .createNewScreen2           = driSWRastCreateNewScreen2,
};

/** Image driver interface */
const __DRIimageDriverExtension driImageDriverExtension = {
    .base = { __DRI_IMAGE_DRIVER, 1 },

    .createNewScreen2           = driCreateNewScreen2,
    .createNewDrawable          = driCreateNewDrawable,
    .getAPIMask                 = driGetAPIMask,
    .createContextAttribs       = driCreateContextAttribs,
};

通过我们前面的总结,我们可以看到dri的extensions的结构galliumdrm_driver_extensions定义在dri2.c中,它其中的实现在dri_util.c


  • gl_context:gl绘制上下文核心结构体
//mesa/src/mesa/main/mtypes.h
/**
 * Mesa rendering context.
 *
 * This is the central context data structure for Mesa.  Almost all
 * OpenGL state is contained in this structure.
 * Think of this as a base class from which device drivers will derive
 * sub classes.
 */
struct gl_context
{
    ...
    /**
    * The current dispatch table for non-displaylist-saving execution, either
    * BeginEnd or OutsideBeginEnd
    */
   struct _glapi_table *Exec;
   
    ...   
    /**
    * Device driver function pointer table
    */
   struct dd_function_table Driver;  
    ...
}


  • st_context:官方没有介绍,我们可以把他理解为状态上下文(state tracker context)
//src/mesa/state_tracker/st_context.h
struct st_context
{
    ...
   struct gl_context *ctx;
   struct pipe_screen *screen;
   struct pipe_context *pipe;
   ...
}


//src/mesa/state_tracker/st_context.c
static void
st_init_driver_functions(struct pipe_screen *screen,
                         struct dd_function_table *functions)
{
   _mesa_init_sampler_object_functions(functions);

   st_init_draw_functions(functions);
   st_init_blit_functions(functions);
   st_init_bufferobject_functions(screen, functions);
   st_init_clear_functions(functions);
        functions->Clear = st_Clear;
            st->pipe->clear(...)、、这里的pipi是pipe_context,且在lp_context中,llvmpipe->pipe.clear = llvmpipe_clear;
   st_init_bitmap_functions(functions);
   st_init_copy_image_functions(functions);
   st_init_drawpixels_functions(functions);
   st_init_rasterpos_functions(functions);

   st_init_drawtex_functions(functions);

   st_init_eglimage_functions(functions);

   st_init_fbo_functions(functions);
// 省略
}

_mesa_Clear
    clear(...)
        ctx->Driver.Clear(...)//此处的ctx为gl_context,Driver为dd_function_table,在前面被赋值

//这块怎么被调用到的详见章节3
struct st_context *
st_create_context(gl_api api, struct pipe_context *pipe,
                  const struct gl_config *visual,
                  struct st_context *share,
                  const struct st_config_options *options,
                  bool no_error)
{
   struct gl_context *ctx;
   struct gl_context *shareCtx = share ? share->ctx : NULL;
   struct dd_function_table funcs;
   struct st_context *st;

   util_cpu_detect();

   memset(&funcs, 0, sizeof(funcs));
   st_init_driver_functions(pipe->screen, &funcs);
   ...
}


  • pipe_context:Gallium渲染上下文
//src/gallium/include/pipe/p_context.h
/**
 * Gallium rendering context.  Basically:
 *  - state setting functions
 *  - VBO drawing functions
 *  - surface functions
 */
struct pipe_context {
   struct pipe_screen *screen;
   void (*draw_vbo)(...);
   ...

看注释,这个结构体蛮厉害的!


  • dd_function_table:这个结构体,起到了承接gl_xxx—>mesa_xxx到st_xxx的作用
//src/mesa/main/dd.h
/**
 * Device driver function table.
 * Core Mesa uses these function pointers to call into device drivers.
 * Most of these functions directly correspond to OpenGL state commands.
 * Core Mesa will call these functions after error checking has been done
 * so that the drivers don't have to worry about error testing.
 *
 * Vertex transformation/clipping/lighting is patched into the T&L module.
 * Rasterization functions are patched into the swrast module.
 *
 * Note: when new functions are added here, the drivers/common/driverfuncs.c
 * file should be updated too!!!
 */
struct dd_function_table {
    ...
   /**
    * Clear the color/depth/stencil/accum buffer(s).
    * \param buffers  a bitmask of BUFFER_BIT_* flags indicating which
    *                 renderbuffers need to be cleared.
    */
   void (*Clear)( struct gl_context *ctx, GLbitfield buffers );    
    ...
}


  • kms_sw_winsys:功能,通过libdrm,和内核drm交互:申请显存(也可能是内存)bo,显存map到内存,查询bo是否忙(正在被显卡使用)

  • llvmpipe_screen:使用kms_swrast并且是llvmpipe做后端,接口类,功能:查询显卡特性参数。另外,注册了资源构造函数。资源指显存资源,如bo,texture,并且现了pipe_screen定义的接口其中注册了一个sw_winsys,以辅助实现pipe_screen定义的接口.screen主要体现硬件的能力,创建和管理资源
struct llvmpipe_screen
{
   struct pipe_screen base;
   struct sw_winsys *winsys;
   ...
}


  • llvmpipe_context继承自pipe_context其中定义了和context相关的函数集context可以认为是硬件的一个pipe line的实例,涉及到state的设置,fence等
struct llvmpipe_context {
   struct pipe_context pipe;  /**< base class */
   ...
}

Setting rendering state (texture sampler state, blending state, rasterization state, vertex array info, drawing surfaces, etc.)
Setting shader state, using the TGSI binary shader representation.
Vertex array and indexed vertex array drawing.

  • pipe_开头函数: pipe_开头的状态对象,是对现代显卡的底层抽象层,是架构无关层




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

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

相关文章

猜猜我是谁游戏

猜谜过程 在TabControl控件中&#xff0c;第一个tab中放了一个PictureBox&#xff0c;里面有一张黑色的图片。 玩家点击显示答案按钮&#xff0c;切换图片。 设计器 private void button1_Click(object sender, EventArgs e){this.pictureBox1.Image Image.FromFile(&qu…

多模态大模型:系统、趋势与问题

引言 多模态大模型是当今人工智能领域的热门方向之一。它不仅能处理文本&#xff0c;还能理解和生成图像、视频、语音等多种模态的数据。这种能力使得多模态大模型在自然语言处理、计算机视觉等多个领域展示出巨大的潜力和应用价值。那么&#xff0c;多模态大模型是如何训练出…

【LeetCode刷题】滑动窗口解决问题:串联所有单词的子串(困难)、最小覆盖子串(困难)

【LeetCode刷题】Day 10 题目1&#xff1a;30. 串联所有单词的子串&#xff08;困难&#xff09;思路分析&#xff1a;思路1&#xff1a;滑动窗口哈希map 题目2&#xff1a;LCR 017.最小覆盖子串思路分析思路1&#xff1a;滑动窗口哈希表 题目1&#xff1a;30. 串联所有单词的子…

MyBatis学习笔记(周五前学完)

MyBatis-Plus是一个MyBatis的增强工具。在MyBatis的基础上只做增强不做改变&#xff0c;为简化开发、提高效率而生。 通过MyBatis-Plus来进行数据插入时&#xff0c;它默认会 使用雪花算法来生成id&#xff0c;长度比较长 增删改的返回值都是统一的&#xff0c;影响的只有行数。…

Matplotlib绘图指南:从基础绘图到多子图展示

目录 前言 导入模块 第一点&#xff1a;绘制图像 第二点&#xff1a;保存图像 第三点&#xff1a;多图形的绘制 第四点&#xff1a;绘制多子图 总结 前言 在数据可视化中&#xff0c;Matplotlib是一款强大的Python库&#xff0c;提供了丰富的功能来绘制各种类型的图表。…

Notepad++不显示CRLF的方法

View -> Show Symbol -> 去掉勾选 Show All Characters

[机缘参悟-191] - 《道家-水木然人间清醒1》读书笔记 -14- 关系界限 - 经济和人格上的独立,走向成熟的必经之路,才能更好的谈其他情感(IT)

目录 前言&#xff1a; 1、“友善的孤独者” 2、“外向的孤独者” 3、道不同不相为谋 4、警惕依赖 5、完整独立的个体 6、不必纠正他人的错误&#xff0c;除非他影响了你 7、不再期待别人能理解自己&#xff0c;只有高维向下兼容你的人才能理解你 8、只有高维和同频的…

有限元之有限元法的实现

目录 一、单元刚度矩阵及单元荷载 二、总刚度矩阵及总荷载的合成 三、边界条件处理 四、算例实现 4.1 C代码 4.2 计算结果 五、结论 前三节我们介绍了有限元的基本概念、变分理论及有限元空间的构造&#xff0c;本节我们探讨如何实现有限元法。我们继续以二维椭圆型方程…

5W 1.5KVDC、3KVDC 宽电压输入 DC/DC 电源模块——TP05DA 系列,广泛应用于通信、铁路等设备中

TP05DA系列电源模块额定输出功率为5W&#xff0c;外形尺寸为31.75*20.32*10.65&#xff0c;应用于2:1及4:1电压输入范围 9V-18V、18V-36V、36V-72V、9V-36V和18V-72VDC的输入电压环境&#xff0c;输出电压精度可达1%&#xff0c;具有输出短路保护等功能&#xff0c;可广泛应用于…

Apache、Nginx、IIS文件解析漏洞

目录 1、文件解析漏洞介绍 2、Apache相关的解析漏洞 &#xff08;1&#xff09;多后缀解析漏洞 &#xff08;2&#xff09;Apache配置问题 &#xff08;3&#xff09;换行符解析漏洞 &#xff08;4&#xff09;罕见后缀解析 3、Nginx相关的解析漏洞 &#xff08;1&…

刷代码随想录有感(82):贪心算法——摆动序列

题干&#xff1a; 代码&#xff1a; class Solution { public:int wiggleMaxLength(vector<int>& nums) {if(nums.size() < 1)return nums.size();int prediff 0;int curdiff 0;int res 1;for(int i 0; i < nums.size() - 1; i){curdiff nums[i 1] - nu…

隆道出席河南ClO社区十周年庆典,助推采购和供应链数字化发展

5月26日&#xff0c;“河南ClO社区十周年庆典”活动在郑州举办&#xff0c;北京隆道网络科技有限公司总裁助理姚锐出席本次活动&#xff0c;并发表主题演讲《数字化采购与供应链&#xff1a;隆道的探索与实践》&#xff0c;分享隆道公司在采购和供应链数字化转型方面的研究成果…

Python在忘mysql密码后该如何重新连mysql

步骤一 先到mysql的bin目录下 步骤二 用mysqld delete mysql 把之前的库删了 步骤三 通过管理员模式进去后 用命令mysqld --skip-grant-tables越过验证 再输入mysql -u root 直达账户 步骤四 用FLUSH PRIVILEGES; ALTER USER rootlocalhost IDENTIFIED BY new_password; 指…

HTML+CSS TAB导航栏

效果演示 这段代码实现了一个名为"Tab导航栏"的效果,它是一个基于CSS的导航栏,包含五个选项卡,每个选项卡都有一个带有渐变背景色的滑块,当用户点击选项卡时,滑块会滑动到相应的位置。同时,选中的选项卡会变为白色,未选中的选项卡会变为灰色。 Code <!DOC…

《python编程从入门到实践》day41

# 昨日知识点回顾 用户注销、注册&#xff0c;限制访问&#xff0c;新主题关联到当前用户 # 今日知识点学习 第20章 设置应用程序的样式并部署 20.1 设置项目“学习笔记”的样式 20.1.1 应用程序django-bootstrap4 # settings.py ---snip--- INSTALLED_APPS [# 我的应用程序…

【论文阅读|cryoET】DeepETPicker:使用弱监督深度学习的快速准确cryoET三维颗粒挑选算法

题目 DeepETPicker: Fast and accurate 3D particle picking for cryo-electron tomography using weakly supervised deep learning 发表期刊&#xff1a; Nature Communications 发表时间&#xff1a;2024.02 Accepted 作者&#xff1a;Guole Liu, Tongxin Niu 中科院自动化…

基于模糊PID控制器的汽车电磁悬架控制系统simulink建模与仿真

目录 1.课题概述 2.系统仿真结果 3.核心程序与模型 4.系统原理简介 5.完整工程文件 1.课题概述 基于模糊PID控制器的汽车电磁悬架控制系统simulink建模与仿真。 2.系统仿真结果 上面的仿真结果是无控制器和LQG的对比&#xff0c;以及有控制器和LQG的对比仿真。 3.核心程…

视觉语音识别挑战赛 CNVSRC 2024

CNVSRC 2024由NCMMSC 2024组委会发起&#xff0c;清华大学、北京邮电大学、海天瑞声、语音之家共同主办。竞赛的目标是通过口唇动作来推断发音内容&#xff0c;进一步推动视觉语音识别技术的发展。视觉语音识别&#xff08;也称为读唇技术&#xff09;是一种通过观察唇部动作推…

Cweek2+3

C语言学习 五.操作符 5.单目操作符(2) sizeof不能用于计算动态分配的内存 在对数组使用sizeof时&#xff0c;返回的是整个数组的大小&#xff08;所有元素的总字节数&#xff09;。而对指针使用sizeof时&#xff0c;返回的是指针本身的大小&#xff08;通常是机器字长的大小…

基础技术-ELF系列2-ELF文件进阶与libelf库

成就更好的自己 本篇是基础技术系列中ELF相关技术的第二篇&#xff0c;将会详细介绍一下ELF文件的结构。 没有看过之前的文章的朋友请重新开始&#xff0c;博主观点比较清奇&#xff0c;否则可能会有一些不太明白的地方&#xff1a; 基础技术-ELF系列(1)-ELF文件基础-CSDN博…