Hot Door CORE Forum
Windows update and OpenGL handling. - Printable Version

+- Hot Door CORE Forum (http://hotdoorcore.com/forum)
+-- Forum: All forums (http://hotdoorcore.com/forum/forumdisplay.php?fid=1)
+--- Forum: General discussion (http://hotdoorcore.com/forum/forumdisplay.php?fid=3)
+--- Thread: Windows update and OpenGL handling. (/showthread.php?tid=154)



Windows update and OpenGL handling. - Gaxx - 11-07-2017

Hello. I've encountered a problem that I'm not sure how to deal with yet, so any advice is welcome. I'm using openGL rendering in my plugin, basic workflow for it is something like this:

Initialization:
Code:
hdi::core::CustomWidget frame(...args);
    CWnd *pWnd = frame.platformWidget();
    HWND mHwnd = pWnd->GetSafeHwnd();
    HDC mHdc = pWnd->GetDC()->m_hDC;
//set pixel format etc
    HGLRC mHglrc = wglCreateContext(mHdc);
        wglMakeCurrent(mHdc, mHglrc);

Then there is some draw routine triggered by hdi::core::Timer.
Something like this:
Code:
void Draw()
{
//setup gl
    glBegin( ... );
//some rendering
    glEnd();
    glFlush();
        SwapBuffers(mHdc);
}

Everything worked perfectly. However when my Win10 updated to version 1709, build 16299.19 the viewport where image should have been became empty. I've checked for context validity and everything seemed fine. Even more - if I flushed rendered context to an image file, it showed me correct results - image was there, its size corresponded to custom widget size that hosted my context. So it seems that opengl works fine.
Only conclusion that I could think of is that Microsoft changed window lifecycle in this update and now all the rendered stuff gets invalidated somehow. Maybe there is a better place for my draw fuction other than timer triggered callback? Or maybe there are some actions I could take that are not obvious to me right now?


RE: Windows update and OpenGL handling. - Gaxx - 11-20-2017

I've done some experimenting with this. I've tried to get a handler for windows native proc for the widget and tinker a little with it so that in case of WM_PAINT default winproc is used and in all other cases old handler is used.

Code:
std::map<HWND, LONG_PTR> oldHandlerMap;

typedef LRESULT (*WndProcType)(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK WndProcTst (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    if(message == WM_PAINT)
    {
        return DefWindowProc(hwnd, message, wParam, lParam) ;
    }

    WndProcType oldHandlerPtr = (WndProcType)oldHandlerMap[hwnd];
    return CallWindowProc((WNDPROC)oldHandlerPtr, hwnd, message, wParam, lParam);
}
void RehookWinProc(const hdi::core::CustomWidget& parent) {
    //return;
    CWnd *pWnd = parent.platformWidget();
    HWND tmpHwnd = pWnd->GetSafeHwnd();

    LONG_PTR oldHandler = GetClassLongPtr(tmpHwnd, GCLP_WNDPROC);
    oldHandlerMap[tmpHwnd] = oldHandler;
    SetWindowLongPtr(tmpHwnd, GWLP_WNDPROC, (LONG_PTR)WndProcTst);
}

Now I can see the graphics, however all the callbacks related to widget like mouse down, mouse up etc are gone. Still trying to figure this out.


RE: Windows update and OpenGL handling. - Gaxx - 11-23-2017

Is it possible to dynamically upload an image (bit buffer) to a label during runtime? This would theoretically resolve my problem since I have my rendered image as a buffer, even though its not displayed since update.


RE: Windows update and OpenGL handling. - Gaxx - 06-05-2018

Hello again. I'm back to this problem again. I've moved all the drawing routines to customWidget draw callback and it partially solved the problem.
Now rendered content is displayed but only on some machines. Namely all machines running on Intel integrated graphic cards still show an empty viewport. If there are any thoughts on what could be causing this or what should I try out I'd be grateful.

Here is a sample code for a redraw callback that simply paints the frame blue.

Code:
    HDC Hdc = *frame.platformDC();    

    int        nPixelFormat;
    PIXELFORMATDESCRIPTOR pfd;

    memset(&pfd, 0x00, sizeof(pfd));
    pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
    pfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_TYPE_RGBA;
    pfd.iPixelType = PFD_TYPE_RGBA;
    pfd.cColorBits = 16;
    pfd.cDepthBits = 24;
    nPixelFormat = ChoosePixelFormat(Hdc, &pfd);

    if (!nPixelFormat)
        return;

    if (!SetPixelFormat(Hdc, nPixelFormat, &pfd))
        return;

    HGLRC Hglrc = wglCreateContext(Hdc);

    wglMakeCurrent(Hdc, Hglrc);

    glClearColor(0, 0, 1, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glFlush();
    SwapBuffers(Hdc);

    wglDeleteContext(Hglrc);
    if (Hdc)
        ReleaseDC(mHwnd, Hdc);



RE: Windows update and OpenGL handling. - garrett - 06-26-2018

I'm sorry for your troubles, Gaxx. We don't use OpenGL for anything internally so this issue is outside our wheelhouse.

Under the hood, the CustomWidget class utilizes MFC to perform its various tasks. MFC is really just a thin C++ wrapper around the Win32 API, so in order to perform drawing we simply respond to the WM_PAINT message. There is very little overhead during our WM_PAINT processing; we effectively just perform a little accounting (i.e. store which widget is currently drawing), get the current platform drawing context (so the class consumer can acquire it later via the CustomWidget::platformDC() method), execute the class consumer's drawing callback, and finally release the platform drawing context. The underlying platform control is created through a standard call to MFC's CWnd::Create() method (itself just a wrapper for Win32's CreateWindow() function).

Given our standard and straightforward use of the MFC API, and given that this problem with OpenGL suddenly appeared after a Windows 10 update, we can draw no other reasonable conclusion than the root culprit being some underlying change in Windows (or a possible change in Illustrator in response to the Windows 10 update, since we are running inside the context of Adobe's executable).

Lastly, we never explicitly wrote our CustomWidget class with the intention of interoperation with OpenGL, and do not use any such functionality ourselves. In fact, upon learning that some consumers of hdi_core were using OpenGL with the CustomWidget class, we were surprised and considered it a "happy accident". Our suggestion is to utilize Win32 or MFC platform code to create your own platform control inside the target window, such that you can manage/maintain all of the functionality of your widget for optimal interoperability with OpenGL.