Screen flickering problem with Imgui OpenGL3 & win32 Backend

  c++, flicker, imgui, opengl, winapi

I am using Imgui OpenGL3 render backend with win32 backend in a DLL I created. With the host program, I only show the UI and render it. But the Imgui screen is constantly flickering. Also, when the host grabs and drags the window and minimizes it to the taskbar, it doesn’t show anything. The background of the host window is visible in black. When the host window loses focus, it flickers again, and if I focus the host window, the flickering decreases.

The method I am following is as follows;

This first part is just the initialize part;

fn_export double imgui_setup(char* hwnd, char* device, char* device_context) {





//Initialize OpenGL and Device Context
devContext = GetDC((HWND)hwnd);

PIXELFORMATDESCRIPTOR pfd =
{
    sizeof(PIXELFORMATDESCRIPTOR),
    1,
    PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,    // Flags
    PFD_TYPE_RGBA,        // The kind of framebuffer. RGBA or palette.
    32,                   // Colordepth of the framebuffer.
    0, 0, 0, 0, 0, 0,
    0,
    0,
    0,
    0, 0, 0, 0,
    24,                   // Number of bits for the depthbuffer
    8,                    // Number of bits for the stencilbuffer
    0,                    // Number of Aux buffers in the framebuffer.
    PFD_MAIN_PLANE,
    0,
    0, 0, 0
};

int pixelFormat = ChoosePixelFormat(devContext, &pfd);
SetPixelFormat(devContext, pixelFormat, &pfd);
glContext = wglCreateContext(devContext);



//


// setup context
IMGUI_CHECKVERSION();
ImGui::CreateContext();

// Enable keyboard navigation, docking, and viewports
ImGuiIO& io = ImGui::GetIO(); (void)io;
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
//io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;
//io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable;

// setup style
ImGui::StyleColorsDark();

// tweak WindowRounding/WindowBg so platform windows can look identical to regular ones.
ImGuiStyle& style = ImGui::GetStyle();
style.WindowRounding = 0.0f;
style.Colors[ImGuiCol_WindowBg].w = 1.0f;




 // Initialize OpenGL loader
#if defined(IMGUI_IMPL_OPENGL_LOADER_GL3W)
bool err = gl3wInit() != 0;
#elif defined(IMGUI_IMPL_OPENGL_LOADER_GLEW)
bool err = glewInit() != GLEW_OK;
#elif defined(IMGUI_IMPL_OPENGL_LOADER_GLAD)
bool err = gladLoadGL() == 0;
#else
bool err = false; // If you use IMGUI_IMPL_OPENGL_LOADER_CUSTOM, your loader is likely to requires    some form of initialization.
#endif
if (err)
{
    fprintf(stderr, "Failed to initialize OpenGL loader!n");
    return 1;
}




// setup platform/renderer bindings
ImGui_ImplWin32_Init((void*)hwnd);

ImGui_ImplOpenGL3_Init("#version 330");



// Subclass GM window to update keyboard/mouse/etc events
SetWindowSubclass((HWND)hwnd, ImGuiGMSSubclassProc, 1, 1);

return 0.0;
}

And render part of my code ;

fn_export double imgui_render() {

ImGui::Render();

ImGuiIO& io = ImGui::GetIO(); (void)io;
glViewport(0, 0, (int)io.DisplaySize.x, (int)io.DisplaySize.y);
glClearColor(clear_color.x, clear_color.y, clear_color.z, clear_color.w);
glClear(GL_COLOR_BUFFER_BIT);
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());

// Update and Render additional Platform Windows
// (Platform functions may change the current OpenGL context, so we save/restore it to make it easier to paste this code elsewhere.
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
{
    HDC backup_current_context = GetDC(hwnd);
    ImGui::UpdatePlatformWindows();
    ImGui::RenderPlatformWindowsDefault();
    //wglMakeCurrent(backup_current_context, glContext);
}
SwapBuffers(devContext);

glDeleteTextures(textureadded, &texture);
textureadded = 0;



return 1;

}

In this way, I can run the DLL from the host program and get the key and mouse clicks. But as I said there is flickering.
Also, memory leak occurs even though I delete the textures with glDeleteTextures (textureadded, & texture).

This part is for creating textures ;

fn_export double imgui_image(char* address,double _ww,double _hh) {

int image_width = _ww;
int image_height = _hh;

glGenTextures(1, &texture);

glBindTexture(GL_TEXTURE_2D, texture);


glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);



glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image_width, image_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, address);


ImGui::Image(reinterpret_cast<void*>(static_cast<intptr_t>(texture)), ImVec2(_ww, _hh));

textureadded++;
texture = NULL;
return 1;
}

The ‘address’ variable I use here is a buffer pointer that I created in the host program and is never changing.

Do you have any suggestions specifically for flickering? Could there be a difference in the refresh rate of the host program and the DLL, ie opengl? Or, according to what I read somewhere, it was saying that it might clear window twice in the same step. But this is not the case for me.

Source: Windows Questions C++

LEAVE A COMMENT