c++winapiopenglmfcglew

Create two OpenGL contexts (views, subwindows) in the one MFC window


I need to make two independent OpenGL views in one MFC dialog-based window. This views will show different scenes with different shaders and different VAO. It's not difficult to me to make the one view. I create Picture Control rectangle and then OnInitDialog() I call this:

BOOL CMYAPPDlg::setRenderingContext()
{
    CWnd* pImage = GetDlgItem(IDC_OF_PICTURE_CONTROL);
    m_pDC = pImage->GetDC();

    static  PIXELFORMATDESCRIPTOR pfd =
    {
        sizeof(PIXELFORMATDESCRIPTOR),
        1 ,
        PFD_DRAW_TO_WINDOW |            
        PFD_SUPPORT_OPENGL |           
        PFD_DOUBLEBUFFER,             
        PFD_TYPE_RGBA,                
        32 ,                            
        0 ,  0 ,  0 ,  0 ,  0 ,  0 ,            
        0 ,                              
        0 ,                             
        0 ,                           
        0  ,  0  ,  0  ,  0  ,  
        24 ,                       
        0 ,                           
        0 ,                            
        PFD_MAIN_PLANE,                 
        0 ,                            
        0 ,  0 ,  0                       
    };

    int pixelFormat = ChoosePixelFormat(m_pDC->GetSafeHdc(), &pfd);
    SetPixelFormat(m_pDC->GetSafeHdc(), pixelFormat, &pfd);
    HGLRC RC_OF_PICTURE_CONTROL= wglCreateContext(m_pDC->GetSafeHdc());
    wglMakeCurrent(m_pDC->GetSafeHdc(), RC_OF_PICTURE_CONTROL);

    glewExperimental = GL_TRUE;
    glewInit();

    GLint attribs[] =
    {
        WGL_CONTEXT_MAJOR_VERSION_ARB,  3 ,
        WGL_CONTEXT_MINOR_VERSION_ARB,  3 ,
        WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
        0
    };

    HGLRC tmpRC = wglCreateContextAttribsARB(m_pDC->GetSafeHdc(), CompHRC, attribs);

    if (tmpRC && wglMakeCurrent(m_pDC->GetSafeHdc(), tmpRC)) RC_OF_PICTURE_CONTROL = tmpRC ;
}

Now I draw the view in OnTimer method and everything works perfect.

void CXENLPTNEWDlg::OnTimer(UINT_PTR nIDEvent)
{
    CDialogEx::OnTimer(nIDEvent);

    glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);

    SwapBuffers(m_pDC->GetSafeHdc());
}

But how can I make two different view for two different Picture Control? Should I make two context? If so, should I call wglMakeCurrent() two times for each view every frame something like that?

void CXENLPTNEWDlg::OnTimer(UINT_PTR nIDEvent)
{
    CDialogEx::OnTimer(nIDEvent);
    

    wglMakeCurrent(m_pDC->GetSafeHdc(), RC_OF_PICTURE_CONTROL_1));

    glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);

    wglMakeCurrent(NULL, NULL);   


    wglMakeCurrent(m_pDC->GetSafeHdc(), RC_OF_PICTURE_CONTROL_2));   

    glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);

    wglMakeCurrent(NULL, NULL); 


    SwapBuffers(m_pDC->GetSafeHdc());
}

Solution

  • You'll need two DC I think, one for each control.

    BTW avoid to store DC, they are limited, scarce resource. Get them, do your stuff then relase them. The overhead is minimal and will avoid you nasty Win32 issues.

    If you are familliar with MFC use a MDI application instead of Dailog based. You then write a single MDIView and instanciate it twice. You'll then use different two timer (one in each view) and implement drawing in the OnPaint() MFC handler.

    Alternatively you can also derive your own Picture control and do the do the OpenGL stuff there.