After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 763287 - GDK-Win32: GL area does not redraw on resize
GDK-Win32: GL area does not redraw on resize
Status: RESOLVED FIXED
Product: gtk+
Classification: Platform
Component: Backend: Win32
unspecified
Other Windows
: Normal normal
: ---
Assigned To: gtk-win32 maintainers
gtk-bugs
Depends on:
Blocks:
 
 
Reported: 2016-03-08 05:44 UTC by Fan, Chun-wei
Modified: 2016-03-10 13:13 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
GDK W32: Partially rollback the custom resize for GL windows (3.97 KB, patch)
2016-03-09 11:56 UTC, LRN
none Details | Review
Apply pending resizes for GL windows before repainting (5.33 KB, patch)
2016-03-09 13:10 UTC, Fan, Chun-wei
none Details | Review
GDK W32: Partially roll back the custom resize for GL windows (5.63 KB, patch)
2016-03-09 16:52 UTC, LRN
none Details | Review
GDK W32: Partially rollback the custom resize for GL windows (5.72 KB, patch)
2016-03-09 16:58 UTC, LRN
none Details | Review
GDK W32: Partially rollback the custom resize for GL windows (5.83 KB, patch)
2016-03-10 13:13 UTC, LRN
committed Details | Review

Description Fan, Chun-wei 2016-03-08 05:44:14 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.
Comment 1 Fan, Chun-wei 2016-03-08 10:44:23 UTC
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.
Comment 2 LRN 2016-03-09 09:37:21 UTC
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).
Comment 3 LRN 2016-03-09 11:56:20 UTC
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.
Comment 4 Fan, Chun-wei 2016-03-09 13:10:34 UTC
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!
Comment 5 LRN 2016-03-09 14:14:56 UTC
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.
Comment 6 LRN 2016-03-09 16:52:20 UTC
Created attachment 323521 [details] [review]
GDK W32: Partially roll back the custom resize for GL windows

Refactored the refactored version of the patch.
Comment 7 LRN 2016-03-09 16:58:46 UTC
Created attachment 323523 [details] [review]
GDK W32: Partially rollback the custom resize for GL windows

Fixed a few issues with the re-refactored patch.
Comment 8 Fan, Chun-wei 2016-03-10 03:44:13 UTC
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...
Comment 9 LRN 2016-03-10 13:13:12 UTC
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).
Comment 10 LRN 2016-03-10 13:13:52 UTC
Attachment 323620 [details] pushed as 65ea6f8 - GDK W32: Partially rollback the custom resize for GL windows