文章目录

  • 前言
    • 源码解析
      • src/glx/single2.c
      • build/src/mapi/glapi/gen/indirect_init.c
      • src/glx/indirect_glx.c
      • src/glx/glxclient.h

前言

GLX支持直接渲染(Direct Rendering)与间接渲染(Indirect Rendering)两种模式,直接渲染模式需要OpenGL应用程序能够直接访问GPU(可以简单地认为OpenGL应用程序与GPU需要在同一台电脑上),而间接渲染则需要将OpenGL指令转发至X Window Server,由X Window Server负责执行真正的OpenGL指令。

所以直接渲染和间接渲染的OpenGL函数应该是两套执行流程,那么Mesa的GLX是如何实现的呢?本篇文章先做一些简单的代码记录,详细解析容后道来。

源码解析

src/glx/single2.c

void
__indirect_glGetFloatv(GLenum val, GLfloat * f)
{const GLenum origVal = val;__GLX_SINGLE_DECLARE_VARIABLES();xGLXSingleReply reply;val = RemapTransposeEnum(val);__GLX_SINGLE_LOAD_VARIABLES();__GLX_SINGLE_BEGIN(X_GLsop_GetFloatv, 4); // 发送请求__GLX_SINGLE_PUT_LONG(0, val);__GLX_SINGLE_READ_XREPLY(); // 读取响应,相当于实现了一个RPC__GLX_SINGLE_GET_SIZE(compsize);if (compsize == 0) {/*** Error occurred; don't modify user's buffer.*/}else {GLintptr data;/*** We still needed to send the request to the server in order to** find out whether it was legal to make a query (it's illegal,** for example, to call a query between glBegin() and glEnd()).*/if (get_client_data(gc, val, &data)) {*f = (GLfloat) data;}else {/*** Not a local value, so use what we got from the server.*/if (compsize == 1) {__GLX_SINGLE_GET_FLOAT(f);}else {__GLX_SINGLE_GET_FLOAT_ARRAY(f, compsize);if (val != origVal) {/* matrix transpose */TransposeMatrixf(f);}}}}__GLX_SINGLE_END();
}

build/src/mapi/glapi/gen/indirect_init.c

/*** Create and initialize a new GL dispatch table.  The table is initialized* with GLX indirect rendering protocol functions.*/
struct _glapi_table * __glXNewIndirectAPI( void )
{_glapi_proc *table;unsigned entries;unsigned i;int o;entries = _glapi_get_dispatch_table_size();table = malloc(entries * sizeof(_glapi_proc));if (table == NULL)return NULL;/* first, set all entries to point to no-op functions */for (i = 0; i < entries; i++) {table[i] = (_glapi_proc) NoOp;}/* now, initialize the entries we understand *//* 1.0 */table[213] = (_glapi_proc) __indirect_glAccum;// 省略table[262] = (_glapi_proc) __indirect_glGetFloatv;// 省略return (struct _glapi_table *) table;
}

src/glx/indirect_glx.c

static int
indirect_bind_context(struct glx_context *gc, struct glx_context *old,GLXDrawable draw, GLXDrawable read)
{GLXContextTag tag;Display *dpy = gc->psc->dpy;Bool sent;if (old != &dummyContext && !old->isDirect && old->psc->dpy == dpy) {tag = old->currentContextTag;old->currentContextTag = 0;} else {tag = 0;}sent = SendMakeCurrentRequest(dpy, gc->xid, tag, draw, read,&gc->currentContextTag);if (sent) {if (!IndirectAPI)IndirectAPI = __glXNewIndirectAPI(); // 死亡凝视_glapi_set_dispatch(IndirectAPI); // 在src/mapi/mapi_glapi.c中定义/* The indirect vertex array state must to be initialised after we* have setup the context, as it needs to query server attributes.** At the point this is called gc->currentDpy is not initialized* nor is the thread's current context actually set. Hence the* cleverness before the GetString calls.*/__GLXattribute *state = gc->client_state_private;if (state && state->array_state == NULL) {gc->currentDpy = gc->psc->dpy;__glXSetCurrentContext(gc);__indirect_glGetString(GL_EXTENSIONS);__indirect_glGetString(GL_VERSION);__glXInitVertexArrayState(gc);}}return !sent;
}static const struct glx_context_vtable indirect_context_vtable = {.destroy             = indirect_destroy_context,.bind                = indirect_bind_context, // 死亡凝视.unbind              = indirect_unbind_context,.wait_gl             = indirect_wait_gl,.wait_x              = indirect_wait_x,.use_x_font          = indirect_use_x_font,.bind_tex_image      = indirect_bind_tex_image,.release_tex_image   = indirect_release_tex_image,.get_proc_address    = NULL,
};/*** \todo Eliminate \c __glXInitVertexArrayState.  Replace it with a new* function called \c __glXAllocateClientState that allocates the memory and* does all the initialization (including the pixel pack / unpack).** \note* This function is \b not the place to validate the context creation* parameters.  It is just the allocator for the \c glx_context.*/
_X_HIDDEN struct glx_context *
indirect_create_context(struct glx_screen *psc,struct glx_config *mode,struct glx_context *shareList, int renderType)
{struct glx_context *gc;int bufSize;CARD8 opcode;__GLXattribute *state;opcode = __glXSetupForCommand(psc->dpy);if (!opcode) {return NULL;}/* Allocate our context record */gc = calloc(1, sizeof *gc);if (!gc) {/* Out of memory */return NULL;}glx_context_init(gc, psc, mode);gc->isDirect = GL_FALSE;gc->vtable = &indirect_context_vtable; // 死亡凝视state = calloc(1, sizeof(struct __GLXattributeRec));gc->renderType = renderType;// 省略
}

src/glx/glxclient.h

这又是一个重要的数据结构

/*** GLX state that needs to be kept on the client.  One of these records* exist for each context that has been made current by this client.*/
struct glx_context
{/*** \name Drawing command buffer.** Drawing commands are packed into this buffer before being sent as a* single GLX protocol request.  The buffer is sent when it overflows or* is flushed by \c __glXFlushRenderBuffer.  \c pc is the next location* in the buffer to be filled.  \c limit is described above in the buffer* slop discussion.** Commands that require large amounts of data to be transfered will* also use this buffer to hold a header that describes the large* command.** These must be the first 6 fields since they are static initialized* in the dummy context in glxext.c*//*@{ */GLubyte *buf;GLubyte *pc;GLubyte *limit;GLubyte *bufEnd;GLint bufSize;/*@} */const struct glx_context_vtable *vtable;/*** The XID of this rendering context.  When the context is created a* new XID is allocated.  This is set to None when the context is* destroyed but is still current to some thread. In this case the* context will be freed on next MakeCurrent.*/XID xid;/*** The XID of the \c shareList context.*/XID share_xid;/*** Screen number.*/GLint screen;struct glx_screen *psc;/*** \c GL_TRUE if the context was created with ImportContext, which* means the server-side context was created by another X client.*/GLboolean imported;/*** The context tag returned by MakeCurrent when this context is made* current. This tag is used to identify the context that a thread has* current so that proper server context management can be done.  It is* used for all context specific commands (i.e., \c Render, \c RenderLarge,* \c WaitX, \c WaitGL, \c UseXFont, and \c MakeCurrent (for the old* context)).*/GLXContextTag currentContextTag;/*** \name Rendering mode** The rendering mode is kept on the client as well as the server.* When \c glRenderMode is called, the buffer associated with the* previous rendering mode (feedback or select) is filled.*//*@{ */GLenum renderMode;GLfloat *feedbackBuf;GLuint *selectBuf;/*@} *//*** Client side attribs.*/__GLXattributeMachine attributes;/*** Client side error code.  This is set when client side gl API* routines need to set an error because of a bad enumerant or* running out of memory, etc.*/GLenum error;/*** Whether this context does direct rendering.*/Bool isDirect;#if defined(GLX_DIRECT_RENDERING) && defined(GLX_USE_APPLEGL)void *driContext;
#endif/*** \c dpy of current display for this context.  Will be \c NULL if not* current to any display, or if this is the "dummy context".*/Display *currentDpy;/*** The current drawable for this context.  Will be None if this* context is not current to any drawable.  currentReadable is below.*/GLXDrawable currentDrawable;/*** \name GL Constant Strings** Constant strings that describe the server implementation* These pertain to GL attributes, not to be confused with* GLX versioning attributes.*//*@{ */GLubyte *vendor;GLubyte *renderer;GLubyte *version;GLubyte *extensions;/*@} *//*** Maximum small render command size.  This is the smaller of 64k and* the size of the above buffer.*/GLint maxSmallRenderCommandSize;/*** Major opcode for the extension.  Copied here so a lookup isn't* needed.*/GLint majorOpcode;/*** Pointer to the config used to create this context.*/struct glx_config *config;/*** The current read-drawable for this context.  Will be None if this* context is not current to any drawable.** \since Internal API version 20030606.*/GLXDrawable currentReadable;/*** Pointer to client-state data that is private to libGL.  This is only* used for indirect rendering contexts.** No internal API version change was made for this change.  Client-side* drivers should NEVER use this data or even care that it exists.*/void *client_state_private;/*** Stored value for \c glXQueryContext attribute \c GLX_RENDER_TYPE.*/int renderType;/*** \name Raw server GL version** True core GL version supported by the server.  This is the raw value* returned by the server, and it may not reflect what is actually* supported (or reported) by the client-side library.*//*@{ */int server_major;        /**< Major version number. */int server_minor;        /**< Minor version number. *//*@} *//*** Number of threads we're currently current in.*/unsigned long thread_refcount;/*** GLX_ARB_create_context_no_error setting for this context.* This needs to be kept here to enforce shared context rules.*/Bool noError;char gl_extension_bits[__GL_EXT_BYTES];
};

GLX直接渲染与间接渲染相关推荐

  1. 小块渲染VS渐进式渲染

    在渲染引擎中,有些渲染引擎支持块两种可续渲染(块渲染与渐进式),例如:V-Ray.Redshift.Corona等.因而在选择渲染方式时,有些用户会游移不定,到底是选择「小块渲染」还是「渐进式渲染」呢 ...

  2. 客户端渲染 服务端渲染_这就是赢得客户端渲染的原因

    客户端渲染 服务端渲染 A decade ago, nearly everyone was rendering their web applications on the server using t ...

  3. mustache 渲染文本一直渲染不出来

    今天在模板上页面上渲染文本 但是渲染了半天,什么也没有渲染出来 为什么呢,你看我前台的html页面如此: <script type="text/x-template" id= ...

  4. 【大前端之前后分离01】JS前端渲染VS服务器端渲染

    前言 之前看了一篇文章:@Charlie.Zheng Web系统开发构架再思考-前后端的完全分离,文中论述了为何要前后分离,站在前端的角度来看,是很有必要的:但是如何说服团队使用前端渲染方案却是一个现 ...

  5. 【Android 性能优化】布局渲染优化 ( CPU 渲染优化 | 减少布局的嵌套 | 测量布局绘制时间 | OnFrameMetricsAvailableListener | 布局渲染优化总结 )

    文章目录 一. 减少布局嵌套 二. 布局渲染时间测量 1. FrameMetrics 使用流程 2. FrameMetrics 参数解析 3. FrameMetrics 代码示例 三. 布局渲染优化总 ...

  6. 服务端渲染vs客户端渲染到前后端同构

    关于服务端渲染与客户端渲染的优劣,互联网上已经有过很多的文章进行过分析,在这里我谈一下我个人的见解. 首先,还是来老生常谈一下关于两种渲染方式的主要优劣: 服务端渲染(仅列出当下最突出的优劣): 优: ...

  7. python 服务端渲染_客户端渲染和服务器渲染的区别

    我们都知道,网页上的很多内容之所以能那么丰富,是因为大量的css.js去渲染出这个页面.那么他们是如何渲染的呢?那么就要说到我们本文的两种渲染方式了,即客户端渲染和服务端渲染. 正文 本文将分别讲述两 ...

  8. 图片渲染延迟_前向渲染与延迟渲染

    如果您开发过3D游戏,那么您可能会在现代图形引擎的研究中遇到术语"前向渲染"和"延迟渲染". 而且,通常,您必须选择一种在游戏中使用.但是它们是什么,它们有什么 ...

  9. 前端后分离深入分析 ——浏览器渲染和服务器渲染区别

    1.为什么会有服务器渲染与客户端渲染? 首先理解服务器和浏览器客户端之间传递的是什么--HTML,CSS,JavaScript的文件以及数据载体json(xml)等文件,而文件都是静态,之所以动态是应 ...

最新文章

  1. 【微信开发】微信开发 之 开启开发模式
  2. docker 查看虚拟网卡_最简单的免费虚拟化方案:Hyper-V Server + Windows Admin Center
  3. 1107: 回文数猜想(函数专题)
  4. (转)Redis上踩过的一些坑-美团
  5. nginx location 匹配 多个规则_后端程序员不得不会的 Nginx 转发匹配规则
  6. 神经网络进行自然语言处理最佳实践
  7. Xtrabackup--InnoDB备份工具介绍(1)
  8. 【数学建模】相关软件
  9. 安徽初二计算机考试试题,安徽省八年级信息技术会考题库
  10. java watcher service_GitHub - sinix/watcher: watcher(守望者)提供java应用暴露监控/健康检查的能力。...
  11. Python爬取URP教务系统课程表并保存到excel
  12. Unity开发VR项目——问题集锦
  13. 终于鸿蒙微内核弄懂了-程序员和鼓励师的合作
  14. 计算机网络原理学习资源——相关书籍推荐
  15. 学习FPGA的网站推荐
  16. Echart - 双柱状图(bar)
  17. 秦皇岛楼市迎来打折潮商家急于回笼资金
  18. 【元宇宙欧米说】一个科幻 NFT,一场关于创作者经济的探索
  19. Ardiuno云门禁
  20. 高德地图 公交站点查询

热门文章

  1. 微软正式发布Windows 7版IE 10
  2. Java读取文件夹下的指定类型的文件(包含子文件夹)
  3. 基于MATLAB负载换流逆变器毕业设计,分享:基于电流内环的单相并网逆变器原理简介及仿真验证...
  4. 厉害了,工信部推出 “一键解绑” 手机号绑定的互联网账号,堪称神器
  5. php wiki 建站,WIKI 建站系统 HDWiki
  6. Docker部署Emqx并配置ssl支持微信小程序
  7. Optitrack Motive软件安装及使用说明
  8. Storefront与NetScaler的集成配置 - part2
  9. Unity动画知识之二:Animator动画状态机
  10. java.util.concurrent同步框架(AQS论文中文翻译)