GNOME Bugzilla – Bug 763287
GDK-Win32: GL area does not redraw on resize
Last modified: 2016-03-10 13:13:56 UTC
Hi, This is another continuation of bug 763080. During the recent commits to have CSD's supported on Windows, the GL area widget is somewhat broken in the sense that the GL area does not redraw[1] (or redraw with artifacts[2]) during or after a resize. After some investigation by rolling back commits in gdk/win32, it was found that the problems were triggered by this commit: e03946bd285d860fc9011a2fbb5363c2a176aaab (GDK W32: custom (non-WM) drag-move and drag-resize code). With blessings, thank you! [1]: In the GL area demo of gtk3-demo, the GL area is not redrawn during or after the resize, possibly as the frame is static. The GL area does show properly once the frames are updated, i.e., by moving the x- y- z-axis sliders. [2]: In the gdkgears test/demo program, the GL area becomes white during the resize, but redraws normally as the frames are updated.
Hi, After some investigation, it does seem to me that we need to handle windows using GL specially, so that we can redraw on resize, in gdk_win32_window_end_paint(). If one is to copy the GL items from gdk_window_end_paint(), the GL area will redraw during the resize, but will flicker and the GL area will become transparent (not drawn) after the resizing is done. After looking at similar code in GDK-Wayland and GDK-Mir, it does seem that we need to copy the cairo surface(s) used in the GL area onto the current paint surface... need to find out how. My thoughts on this, with blessings.
You're right, commenting out the SetWindowPos() call in gdk_win32_window_end_paint() does "fix" this (GL area is being redrawn; obviously, with window not changing its size, the result is...bad, but that's not the point). So maybe this can be fixed by doing a partial rollback of the custom resize code (i.e. call SetWindowPos() immediately instead of delaying it until after the paint; also, there's my first version of the custom resize code, which did resize *before* the paint, we could try that too).
Created attachment 323501 [details] [review] GDK W32: Partially rollback the custom resize for GL windows If a window is being drawn by OpenGL, we need to apply any pending resizes to it *before* we paint.
Created attachment 323505 [details] [review] Apply pending resizes for GL windows before repainting Hi LRN, Thanks for the patch, I think it works. I did refactor your patch a bit (credits still to you :) ), so that we don't duplicate code in 2 places though. With blessings, thank you!
Review of attachment 323505 [details] [review]: ::: gdk/win32/gdkwindow-win32.c @@ +196,3 @@ } +/* Return true if repainting is already done */ That is not what begin_paint() returns. It returns TRUE if GDK should create a surface for this window, and FALSE if it should not. TRUE means that GDK creates an image surface and all cairo drawing is done on that surface. Afterwards the surface is blitted into window. In case of OpenGL drawing the surface is always created (regardless of what begin_paint() returns). FALSE means that cairo draws directly on a surface that is made from the window. Layered windows require TRUE, but we cheat and return FALSE, while providing our own surface, because we can't draw "on" a layered window - we must instead draw on a surface, which will then be fed to UpdateLayeredWindow() (actually, right now what we're doing is slightly unoptimal - we're drawing on an image surface, then blit that into a DC-backed surface, then feed that DC to UpdateLayeredWindow(); i'm planning to optimize that). Yeah, it's kind of complicated. Non-layered windows return TRUE. Now, come to think of it, i'm not sure why the old code (before i started tearing W32 GDK backend apart) returned TRUE (well, it simply didn't implement this function, which is the same as returning TRUE). OpenGL windows require TRUE (i'm a bit fuzzy about the GL drawing process; my best guess is that cairo-drawn stuff is made into a texture and then draw on a window with GL, which is why cairo is given an image surface, as it can't draw directly on a GL window). @@ +204,3 @@ + + if (window == NULL || GDK_WINDOW_DESTROYED (window)) + return TRUE; In light of the above comment: TRUE is returned here because we can't tell whether the window needs or doesn't need a surface. Assume that it does need it. @@ +246,3 @@ { GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (window->impl); + RECT window_rect = {0,}; I understand why you do it, but there's another way - pass NULL to gdk_win32_window_process_paint(), and change gdk_win32_window_process_paint() to to use its own local variable and not put anything into that rect if it's NULL.
Created attachment 323521 [details] [review] GDK W32: Partially roll back the custom resize for GL windows Refactored the refactored version of the patch.
Created attachment 323523 [details] [review] GDK W32: Partially rollback the custom resize for GL windows Fixed a few issues with the re-refactored patch.
Review of attachment 323523 [details] [review]: Hi LRN, Thanks, and I think you have much better understanding in the whole GDK-Win32 internals than I do, especially as you modernized lots of stuff here. I think we should get this in--just one minor thing that I noted... With blessings, thank you! ::: gdk/win32/gdkwindow-win32.c @@ +221,3 @@ + +static void +gdk_win32_window_apply_queued_move (GdkWindow *window, RECT *window_rect) Not that much of an issue, but we could just use RECT instead of a RECT *, but anyways...
Created attachment 323620 [details] [review] GDK W32: Partially rollback the custom resize for GL windows Adjusted as suggested, also more formatting fixes (since nacho isn't around to nag about them).
Attachment 323620 [details] pushed as 65ea6f8 - GDK W32: Partially rollback the custom resize for GL windows