Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Results 1 to 6 of 6

Thread: Accessing another Window's frame buffer

  1. #1
    Junior Member Newbie
    Join Date
    May 2012
    Posts
    5

    Accessing another Window's frame buffer

    Hi,

    I'm hoping to read the frame buffer of a VBS2 window via the VBS2 supplied plugin functionality. Code as follows:-

    HWND vbs2_hWnd = NULL;
    RECT rect;
    vbs2_hWnd = FindWindow(NULL,L"VBS2");
    GetWindowRect(vbs2_hWnd,&rect);

    HDC hdc=GetDC(vbs2_hWnd);

    PIXELFORMATDESCRIPTOR pfd;


    ZeroMemory( &pfd, sizeof( pfd ) );
    pfd.nSize = sizeof( pfd );
    pfd.nVersion = 1;
    pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
    pfd.iPixelType = PFD_TYPE_RGBA;
    pfd.cColorBits = 24;
    pfd.cDepthBits = 32;
    pfd.iLayerType = PFD_MAIN_PLANE;


    int format = ChoosePixelFormat( hdc, &pfd );
    bool pixelFormatSet = SetPixelFormat( hdc, format, &pfd );
    HGLRC mhRC = wglCreateContext( hdc );

    bool madeCurrent = wglMakeCurrent( hdc, mhRC );
    GLenum err = glGetError();
    if (err!=0)
    printf("wglMakeCurrent error = %d\n",err);

    DWORD dwBmpSize = (rect.right-rect.left)*(rect.bottom-rect.top)*4;

    lpbitmap = (char*)malloc(dwBmpSize);

    glReadBuffer(GL_BACK);
    err = glGetError();
    if (err!=0)
    printf("glReadBuffer error = %d\n",err);

    err = glewInit();
    if (err!=0)
    printf("glewInit error = %d\n",err);
    GLuint pboBuffer;
    glGenBuffers(1,&pboBuffer);
    glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB,pboBuffer);
    glBufferData(GL_PIXEL_PACK_BUFFER_ARB,dwBmpSize,0, GL_STREAM_READ);

    err = glGetError();
    if (err!=0)
    printf("SwapBuffers error = %d\n",err);

    glReadPixels(0,0,rect.right-rect.left,rect.bottom-rect.top,GL_RGBA,GL_UNSIGNED_BYTE,0);
    err = glGetError();
    if (err!=0)
    printf("glReadPixel error = %d\n",err);
    memcpy(lpbitmap,glMapBuffer(GL_PIXEL_PACK_BUFFER_A RB,GL_READ_ONLY_ARB),dwBmpSize);
    glUnmapBuffer(GL_PIXEL_PACK_BUFFER_ARB);


    free(lpbitmap);
    wglMakeCurrent(NULL,NULL);
    wglDeleteContext(mhRC);

    Everything seems to work fine except there's no data (00 00 00 FF per pixel). I know the context's correct because if I swap buffers it mucks things up in precisely the way one might expect.

    Is it actually possible to read another Windows image data in this way? I can imagine that writing might be contentious.

    I've already done it using BitBlt etc. and this works fine, but I had hoped to get the depth data for some laser range simulation and make it run a bit quicker.

    Thanks

    John

  2. #2
    Advanced Member Frequent Contributor
    Join Date
    Jan 2012
    Location
    Australia
    Posts
    736
    What is VBS2? Are its windows' content created via OpenGL?

  3. #3
    Junior Member Newbie
    Join Date
    May 2012
    Posts
    5
    Quote Originally Posted by tonyo_au View Post
    What is VBS2? Are its windows' content created via OpenGL?
    Hi Tonyo,

    VBS2 is a commercial distributed multi-user battle simulation gaming product and the answer to the second question is 'I don't know'. VBS2 is Windows only, but I had assumed that as the underlying hardware is identical whichever driver is used (I guess the other option is DirectX) then either method would do. Is this not the case? I suppose it could depend on where the concept of, for example, a framebuffer, exists. If this is a software construct in OpenGL that has no analogue in DirectX then I can see that I might get nowhere. Or I am I talking bollocks. I'll try and do the same thing in DirectX (which I have never used) .


    John

  4. #4
    Advanced Member Frequent Contributor
    Join Date
    Jan 2012
    Location
    Australia
    Posts
    736
    I don't know if you can use OpenGl to grab any generic window. I would not think it would work but as a minimum you need to change glReadBuffer(GL_BACK); to glReadBuffer(GL_FRONT); becuase the only buffer you know actually exists is the window
    currently displayed on the screen. glReadBuffer(GL_BACK) wants to read from the back buffer in a double buffer system and it will be different in OpenGL and DirectX and you don't know if they even use one.

    I know OpenGL and DirectX buffers differ slightly because there is a specific call in OpenGL to bind to a DirectX buffer. A buffer is created with specific information about it's format like whether is has a alpha field, are the colour components (RGB) 8 bit, 32 bit, integer or float, does it have a depth buffer and a stencil buffer. As you can might expect information is held differently in OpenGL to DirectX. And of couse DirectX has several different formats (DirectX 9, DirectX10 etc).

    If you want to grab the frame, and the plug-in doesn't provide a function to do this, I would look at some Windows screen capture code. Basically you create a device compatible bitmap and blit to this bitmap. Now you can grab the bits and save them as you like. These are all Windows function calls. Be warned though if a window overlaps the one you are capturing you will get part of that window in the captured frame.

  5. #5
    Super Moderator OpenGL Guru
    Join Date
    Feb 2000
    Location
    Montreal, Canada
    Posts
    4,421
    No, you can't read the GL surface of another process. If the plugin runs in the same process as the VBS2, then you should be able to do it (just like it is possible to do it in Blender). In Blender, we just call gl functions. There is no need to create a gl context because it uses Blender's GL context. You seem to be creating a GL context and that obviously isn't going to work.

    If the program is using Direct3D, then you would have to ask on the Direct3D forums.
    ------------------------------
    Sig: http://glhlib.sourceforge.net
    an open source GLU replacement library. Much more modern than GLU.
    float matrix[16], inverse_matrix[16];
    glhLoadIdentityf2(matrix);
    glhTranslatef2(matrix, 0.0, 0.0, 5.0);
    glhRotateAboutXf2(matrix, angleInRadians);
    glhScalef2(matrix, 1.0, 1.0, -1.0);
    glhQuickInvertMatrixf2(matrix, inverse_matrix);
    glUniformMatrix4fv(uniformLocation1, 1, FALSE, matrix);
    glUniformMatrix4fv(uniformLocation2, 1, FALSE, inverse_matrix);

  6. #6
    Junior Member Newbie
    Join Date
    May 2012
    Posts
    5
    Thanks guys. I think that pretty much wraps it up. The VBS2 plugin functionality is a dll with a defined interface with a procedure that's called every frame. I imagine that constitutes being part of the same process. I'm pretty sure I tried using the OpenGL calls without defining a context and that just failed. I'll try the DirectX stuff and see if I get a result. If I get anywhere using OpenGL I'll report back.

    Thanks again

    John

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •