如何在第三方进程中隔离我自己的 OpenGL 调用?

Posted

技术标签:

【中文标题】如何在第三方进程中隔离我自己的 OpenGL 调用?【英文标题】:How to isolate my own OpenGL calls inside a third-party process? 【发布时间】:2014-12-20 13:33:22 【问题描述】:

我正在编写一个小工具,在封闭源代码的游戏之上绘制 OpenGL 覆盖。游戏使用 SDL,所以我只是挂在SDL_GL_SwapWindow 并做我自己的事情。但是,这种挂钩会导致游戏本身产生一些副作用。我找到了一个解决方案,它基本上用不推荐使用的glPushAttrib/glPopAttrib 围绕我自己的调用。但这只能解决一半的问题。我仍然在游戏中随机纹理闪烁(我的意思是游戏纹理,我的显示很好)。这种闪烁的原因可能是什么?我自己的纹理会干扰游戏纹理吗?我需要隔离自己的呼叫吗?我该怎么做?

【问题讨论】:

【参考方案1】:

这种闪烁的原因可能是什么?

如果游戏使用着色器,则 glPushAttrib / glPopAttrib 将不会处理您可能正在使用的所有状态。属性堆栈已被弃用,程序可能会使用它覆盖的状态,或者兼容性配置文件中的某些属性位已被重用或扩展以覆盖更多状态。我建议完全不要使用属性堆栈,因为它很难正确。

我自己的纹理会干扰游戏纹理吗?

是的。假设您在一个纹理单元中保留了一个激活的 2D 纹理,该纹理单元稍后将用于 1D 纹理。如果主机程序使用着色器,则 GL_TEXTURE_2D 将优先于 GL_TEXTURE_1D。这是 OpenGL 的一种(恕我直言)设计选择,您可以将多个纹理目标同时绑定到同一个纹理单元,并且使用哪个纹理目标来传递纹素取决于各个目标的优先级。

我需要隔离我自己的电话吗

是的。

我该怎么做?

两种可能的解决方案:

    为您自己的东西创建单独的 OpenGL 上下文。使用wgl,glXGetCurrentContextwglGetCurrentDC,glXGetCurrentDrawable 检索OpenGL 上下文和在您“跳跃”时处于活动状态的drawable。如果您还没有上下文,您可以使用刚刚检索到的drawable 创建一个匹配的OpenGL 上下文.可选择安装命名空间共享。切换到您的上下文,绘制您的东西并切换回主机程序的。 – 主要缺点:切换 OpenGL 上下文非常昂贵。

    在切换状态之前,使用glGet… 检索在此之前的活动状态并在返回主机程序之前恢复旧状态。

【讨论】:

我已经在使用第二种方法了。我为glEnable 分配了堆栈分配的帮助程序类,它将所有内容恢复到析构函数中,但似乎它没有帮助,或者在我的调用过程中我正在更改其他一些东西。游戏确实使用了着色器,因此问题与纹理无关。 第一种方法似乎是我真正需要的。但是影响游戏性能是不可取的。我(可能)必须在每一帧切换上下文。我以前从未使用过这个函数,也不知道“上下文”到底是什么,但我会试试看。 @Xpast:OpenGL 中的一切都取决于渲染上下文。了解 OpenGL 上下文是什么以及它们如何表现它对于任何类型的高级 OpenGL 编程都至关重要。简而言之,OpenGL 上下文有点像一个“类实例”,其中收集了所有纹理、着色器、帧缓冲区对象和状态。这允许操作系统在进程之间隔离 OpenGL 操作,同时也允许一个进程隔离事物。上下文也可以是“连接的”,因此它们共享数据,但状态是分开的。 @Xpast:除了glEnable 之外,还有更多的 OpenGL 状态,几乎每个 绘制内容的 OpenGL 调用都是状态更改操作。如果您查看每个 OpenGL 函数的参考文档,它们中的大多数都有“Associated Gets”部分,它指定更改了哪些状态以及如何查询它。

以上是关于如何在第三方进程中隔离我自己的 OpenGL 调用?的主要内容,如果未能解决你的问题,请参考以下文章

Docker是如何实现隔离的

如何使作业/线程与崩溃隔离

如何在 C++ 和 OpenGL 中分析我自己的函数?

31互斥锁与进程间通信

由事务隔离级别分隔的并发进程死锁

我在哪里需要切换激活上下文?