-1

I'm writing a plugin(i.e. a .dll) for graphics engine that is written in OpenGL. My goal is to mirror what is on that window on a second window. The good news is the graphics engine exposes handles to the device context(hDC), rendering context(hRC), and the rendering window (hWnd). The other good news (I think) is that since my plugin is loaded as a .dll, it is loaded into the same address space, so there wouldn't be any access violations with what I want to achieve.

My goal is to capture the pixels from the graphics engine and draw them into a separate window and thus mirror the display(e.g. SDL2, glfw, or even just a regular Win32 window). My understanding is that I need to use the context of the graphics engine, and then I can then I could do something like read from the framebuffer of the graphics engine to mirror the pixels on my second window in a separate texture.

But how do I go about sharing the context so that I can access the textures and such?

I'm looking at this which may have some useful functions (wglmakecurrent, wglGetCurrentContext, etc.) for achieving this task.

Can anyone confirm I am on the right track, or point me to some resources explaining this idea?

Other Relevant stuff:

  • Working in Windows 10
  • Programming in C and C++

EDIT

Here is what I tried in the .dll I laoded in order to capture pixels from the main applications framebuffer:

   // 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);

Unfortunately I just get garbage data back. Am I on the right track? I tried creating a texture in the next context just to see if it's value was greater than 1, but it was not, which I think is telling me the context is not being shared (otherwise a unique texture id would have been returned).

Mike
  • 81
  • 7
  • Go ahead. Implement your pixels-copy routine. Sharing the context is not neccessary, but it will improve the whole thing because shared contexts share the textures, so you don't need to copy to RAM, but directly redraw in the other window (all by OGL commands). Prefer the SDL/GLFW commands for handling contexts. – Ripi2 Oct 09 '20 at 00:10
  • Even you don't need two contexts. Just set the context as current to the window you want to draw to. – Ripi2 Oct 09 '20 at 00:21
  • Okay thank you very much, I will try to see if it will just works. For clarity, the application that is loading the plugin may be using some other framework (e.g. SDL2), and I would be using GLFW. i suppose I am making the assumption that wglmakecurrent or wglGetCurrentContext, etc. are working with the OpenGL driver and thus would share the same object. – Mike Oct 12 '20 at 03:27

1 Answers1

1

I was able to figure it out, and I am posting a solution as I have yet to see anyone else post a working snippet or the correct order. Perhaps there is a leaner solution out there, but this is what worked for loading a plugin (as a .dll) in another application on Windows 10.

// 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.
Mike
  • 81
  • 7