首页 > 解决方案 > 在 Windows 上共享 OpenGL 上下文

问题描述

我正在为用 OpenGL 编写的图形引擎编写一个插件(即 .dll)。我的目标是在第二个窗口上镜像该窗口上的内容。好消息是图形引擎向设备上下文 (hDC)、渲染上下文 (hRC) 和渲染窗口 (hWnd) 公开句柄。另一个好消息(我认为)是,由于我的插件是作为 .dll 加载的,因此它被加载到相同的地址空间中,因此我想要实现的目标不会有任何访问冲突。

我的目标是从图形引擎捕获像素并将它们绘制到一个单独的窗口中,从而镜像显示(例如 SDL2、glfw,甚至只是一个普通的 Win32 窗口)。我的理解是我需要使用图形引擎的上下文,然后我可以做一些事情,比如从图形引擎的帧缓冲区中读取,以将第二个窗口上的像素镜像到单独的纹理中。

但是我如何去共享上下文以便我可以访问纹理等?

我正在研究这个可能有一些有用的函数(wglmakecurrent、wglGetCurrentContext 等)来完成这个任务。

谁能确认我走在正确的轨道上,或者向我指出一些解释这个想法的资源?

其他相关资料:

编辑

这是我在加载的 .dll 中尝试的,以便从主应用程序帧缓冲区中捕获像素:

   // Make the current context available
   wglMakeCurrent(mainApplication.hDC, mainApplication.hRC);

   glReadBuffer(GL_BACK);
   glPixelStorei(GL_PACK_ALIGNMENT, 1);
   glReadPixels(0, 0, 400, 400, GL_RGBA, GL_UNSIGNED_BYTE, framebufferCapture);

不幸的是,我只是得到了垃圾数据。我在正确的轨道上吗?我尝试在下一个上下文中创建纹理只是为了查看它的值是否大于 1,但事实并非如此,我认为这告诉我上下文没有被共享(否则会返回一个唯一的纹理 ID)。

标签: c++windowsopenglframebuffer

解决方案


我能够弄清楚,并且我正在发布解决方案,因为我还没有看到其他人发布工作片段或正确的顺序。也许有一个更精简的解决方案,但这适用于在 Windows 10 上的另一个应用程序中加载插件(作为 .dll)。

// I had to use some of the wgl functions.
// Note that I wrote my own and added an '_' in front of each of the commands.
HGLRC beforeHGLRC = _wglGetCurrentContext("before glfwMakeContextCurrent");
HDC beforeHDC = _wglGetCurrentDC("before glfwMakeContextCurrent");

// Setting an error callback in front of glfw was useful just to make sure
// the setup worked.
glfwSetErrorCallback(errorCallback);

// Here I initialized glfw
// I knew from my source application the version was 4.6, so
// I set the window to match.
// I think I could probably otherwise query from the context the
// version if I was not sure, but I have yet to do that.
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
glfwWindowHint(GLFW_CENTER_CURSOR, false);

// Now I can create my openGL window from glfw.
GLFWwindow* window = glfwCreateWindow(400, 400, "test window", NULL, NULL);


if (window == NULL){
    glfwTerminate();
}

// Now I can make a new context at this point
glfwMakeContextCurrent(window);

// Now I should see a different context at this point
HGLRC afterHGLRC = _wglGetCurrentContext("after glfwMakeContextCurrent");
HDC afterHDC = _wglGetCurrentDC("after glfwMakeContextCurrent");

// And finally, I can share the lists.
_wglShareLists(beforeHGLRC,afterHGLRC);

// I was able to further debug to see that I had in fact shared the
// contexts by simply creating a texture (glGenTexture). The value
// returned was greater than 1 (in fact it was 28), so then I iterated
// through each of the 28 textures and output the pixels (glGetTexImage) and
// output the textures from the original application to .ppm images.

推荐阅读