Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
Bug 334169 - [Win32] Sash and Tree cause GLCanvas drawing artifacts on Windows 7 + Aero effects
Summary: [Win32] Sash and Tree cause GLCanvas drawing artifacts on Windows 7 + Aero ef...
Status: CLOSED WONTFIX
Alias: None
Product: Platform
Classification: Eclipse Project
Component: SWT (show other bugs)
Version: 3.6   Edit
Hardware: PC Windows 7
: P3 normal with 9 votes (vote)
Target Milestone: ---   Edit
Assignee: Platform-SWT-Inbox CLA
QA Contact:
URL:
Whiteboard: stalebug
Keywords:
Depends on:
Blocks:
 
Reported: 2011-01-12 16:44 EST by Steven Darnell CLA
Modified: 2020-06-17 14:26 EDT (History)
8 users (show)

See Also:


Attachments
Snippet that demonstrates a tree improperly drawing its background on a GLCanvas (1.06 MB, application/octet-stream)
2011-10-10 16:04 EDT, Steven Darnell CLA
no flags Details
snippet showing the problem without Tree (4.81 KB, text/plain)
2011-12-20 10:10 EST, Felipe Heidrich CLA
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Steven Darnell CLA 2011-01-12 16:44:23 EST
Build Identifier: 3.6.0

I have an RCP app with a two-child SashForm where one child is a GLCanvas.  Dragging the sash into the GLCanvas causes the gray background of the window to draw on top of the GLCanvas wherever the sash divider is drawn.  A GL redrawing event clears the problem.

I have also observed that Tree widgets with contents requiring horizontal scroll bars similarly interact with the GLCanvas.  When the tree is on the canvas's right side, horizontally scrolling the tree causes a gray rectangle (with the height of the tree and the width of the scrolled area) to draw on top of the canvas.  This does not occur when the tree is to the right of the canvas.  Again, redraw clears the problem.

These problems are observed on both Windows 7 and Vista.  You can work around both problems by disabling Aero (a.k.a. desktop composition) effects.  This bug is distinct from (but might be related to) Bug 196884: [OpenGL] GLCanvas doesn't work on Vista.

Reproducible: Always

Steps to Reproduce:
1. Drag sash on top of GLCanvas, observe drawing artifact
2. Horizontally scroll Tree "into" GLCanvas, observe drawing artifact
3. Redraw event clears artifacts
4. Disabling Aero prevents problem
Comment 1 Steven Darnell CLA 2011-02-28 23:58:12 EST
Build Identifier: 3.6.2

I am working around the SashForm problem by instead using a Sash and forcing the GLCanvas to resize itself dynamically.  Of note, the SashForm resizes the GLCanvas dynamically on Mac but not Windows.

I still have not found a satisfactory solution for the CheckBoxTreeViewer.  After some experimenting, I noticed that the drawing error only occurs when using an arrow button or dragging the thumb to scroll; however, the drawing error _*does not*_ occur when clicking in the increment/decrement area around the thumb.

Does anyone have any ideas what would account for this difference?
Comment 2 Felipe Heidrich CLA 2011-03-01 10:23:58 EST
(In reply to comment #1)
> Build Identifier: 3.6.2
> I am working around the SashForm problem by instead using a Sash and forcing
> the GLCanvas to resize itself dynamically.  Of note, the SashForm resizes the
> GLCanvas dynamically on Mac but not Windows.

You can ceate the SashForm passing SWT.SMOOTH to make it resize dynamically.

> I still have not found a satisfactory solution for the CheckBoxTreeViewer. 
> After some experimenting, I noticed that the drawing error only occurs when
> using an arrow button or dragging the thumb to scroll; however, the drawing
> error _*does not*_ occur when clicking in the increment/decrement area around
> the thumb.
> Does anyone have any ideas what would account for this difference?

For the application the difference is only the value of event.detail.
See Scrollbar#wmScrollChild
In SWT I don't think there is any difference, see Scrollable#wmScroll
Comment 3 Steven Darnell CLA 2011-10-10 16:04:20 EDT
Created attachment 204902 [details]
Snippet that demonstrates a tree improperly drawing its background on a GLCanvas

GLCanvas code snippet that demonstrates the tree interaction behavior described in Bug #334169. Snippet is based on a JOGL 1.1.1a example; the JOGL dependency is included in the zip file.
Comment 4 Steven Darnell CLA 2011-10-10 16:09:40 EDT
I followed the path through WM_HSCROLL and related methods in Tree, Scrollable, and ScrollBar.java, but could not find any meaningful differences between the way SB_LINEUP/SB_LINEDOWN and SB_PAGEUP/SB_PAGEDOWN are treated.

My coworker suggested that I look at how the tree repaints itself, speculating that larger step scrolling forces a full repaint of the tree while small incremental scrolling uses an optimization to sidestep the full calculation. I believe he is on the right track.

I created an SWT snippet (attached to bug) to better characterize the behavior. If the tree is sufficiently narrow, clicking in the increment/decrement area around the thumb produces the same bad widget-background-in-the-GLCanvas behavior. Presumably, the step is small enough to warrant using the optimized repaint behavior.

Do these observations spark any ideas on the cause or how to fix this behavior? If it helps, the bad behavior is not observed on Windows XP nor on Windows Vista/7 with desktop composition (a.k.a Aero effects) disabled.
Comment 5 Steven Darnell CLA 2011-10-11 16:18:05 EDT
I misspoke in my previous comment. I never reach Tree.WM_HSCROLL(), Scrollable.HSCROLL(), or Control.WMHSCROLL() when I set breakpoints in those methods and use the horizontal scroll bar in my example, GLCanvasTreeSnippet.java.

In contrast, I reach Tree.WM_VSCROLL when using the tree's vertical scroll bar. In my other example, GLCanvasTableSnippet, I reach Table.WM_HSCROLL when I use the table's horizontal scroll bar.

Is this a tree-specific SWT bug, or is this designed behavior?

Could the background drawing error be the result of not sending the OS.TVM_SETEXTENDEDSTYLE and OS.TVS_EX_DOUBLEBUFFER style messages found in Tree.WM_HSCROLL to the tree?

I would really appreciate it if someone from the SWT team could comment on this bug. I am one breath away from being completely over my head.
Comment 6 Felipe Heidrich CLA 2011-12-19 15:35:57 EST
I can't reproduce the first problem (dragging the sash), but I can reproduce the second one (scrolling tree).

When a tree has columns, it is implemented in SWT with two handles (hwndParent=composite, handle=TreeView32). The scrolling is done by SWT in Tree#windowProc() by calling wmScroll() to set the scrollbars followed by setScrollWidth() which scrolls handle within hwndParent.

I tried a couple things.

Tree without columns->problem does not happen.
a generic composite scrolling a large canvas (instead of the tree)->problem happens.
The code is (GLCanvasTreeSnippet):
public static void main(String [] args) {
	final Display display = new Display();
	Shell shell = new Shell(display);
	shell.setLayout(new FillLayout());
	SashForm sashForm = new SashForm(shell, SWT.HORIZONTAL | SWT.SMOOTH );
	GLData data = new GLData ();
	data.doubleBuffer = true;
	final GLCanvas canvas = new GLCanvas(sashForm, SWT.NONE, data);
//	CreateTreeWithColumns.createSampleTree(sashForm);
	ScrolledComposite composite = new ScrolledComposite(sashForm,  SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER);
	Canvas c = new Canvas(composite, 0);
	c.setSize(2000, 2000);
	composite.setContent(c);
	sashForm.setWeights(new int[] { 3, 1 });
... 


It seems that scrolling a sibling window over the GLCanvas does cause it to require a redraw. Not sure how to avoid it.
Comment 7 Steven Darnell CLA 2011-12-19 19:25:25 EST
[Apologies in advance for the length of this comment]

I spoke with Wade Walker from the JOGL2 project and here are some of his conjectures:

To me, this looks like a bug in the SWT framework somewhere, rather than in the SWT GLCanvas itself. Perhaps another SWT window lacks the WS_CLIPCHILDREN or WS_CLIPSIBLINGS style, or draws into a wrongly-sized device context. The fact that the overdraw is grey implies that this is the background erase for some adjacent control.

-----

The problem does seem to be specific to TreeViewer. When I try horizontal scrolling with a TableViewer in the same position relative to a GL canvas, I don't see the overdraw. So the TreeViewer class is definitely a good place to start.

Looking at the SWT source code, specifically in the org.eclipse.swt.widgets.Tree class that's instantiated inside TreeViewer, there's tons of fiddly code that creates graphics contexts and draws into them. I'll bet that one of those is setting the size, position, or clip region of the GC incorrectly so that it extends outside the TreeViewer and allows overdraw of the GLCanvas.

Speculation: You wouldn't notice this with TreeViewer adjacent to other "normal" controls, because they're also using Windows GCs to render, and they probably all have WS_CLIPSIBLINGS|WS_CLIPCHILDREN set so they can't overdraw each other :) But the GL canvas is outside this system, so we can see the overdraw in that case.

-----

Found another clue -- I noticed that the overdraw to the right of the TreeViewer doesn't happen when there's a vertical scroll bar visible in the TreeViewer. So if I fill up (or open items inside) the TreeViewer enough so that a vertical scroll bar appears, the problem stops.

This may help narrow down the code within Tree or TreeViewer that's responsible for this problem. I'll bet their GC width or clipping region calculation is just wrong for the case where vertical scrolling is enabled, but the vertical scroll bar hasn't appeared yet.

-----

Another possibility: Since the overdraw is gray, the problem could be an WM_ERASEBKGND for a child window that gets processed before the child is properly resized or masked to keep it from protruding into the GL canvas (I assume the horizontal scrollbar moves the child windows, then allows them to repaint in their new shifted locations). So you might also need to try commenting out or disabling WM_ERASEBKGND for the various child controls to see if you can find the offending control that way.

==========

One last piece of documentation which might be useful:

The OpenGL Pipeline Newsletter - Volume 003
OpenGL and Windows Vista
http://www.opengl.org/pipeline/article/vol003_7/

On the other hand, if a developer wants to have Windows Aero enabled with a windowed OpenGL application, use the following rules to verify that you are not inadvertently trying to mix GDI over OpenGL:

* Create an OpenGL context using a pixelformat with compositing support (PFD_SUPPORT_COMPOSITION set).
* Handle the application window's WM_ERASEBKGND by returning non-zero in the message handler (this will avoid GDI clearing the OpenGL windows' background).
* Verify that the OpenGL window has the proper clipping styles WS_CLIPCHILDREN or WS_CLIPSIBLINGS, so GDI rendering of sibling windows in the layout hierarchy is not painted over and vice versa.
* Repaint the application's windows as they are being resized rather than when the final resize happens. This will avoid interacting with GDI's xor drawing of the window border. For example, if the application has splitter bars in a four-viewport application, resize the viewports as the splitter bar is being dragged, otherwise GDI xor rendering over the OpenGL viewport will leave trails.
* Do not use GDI for xor drawing of "rubberbands" or selection highlighting over the OpenGL rendering. Use OpenGL logical operations instead.
* Do not get the desktop's DC and try to paint over it with GDI, as it will corrupt the 3D-accelerated regions.
* Under the DWM's new architecture it is especially important that an application developer verify that the application pairs GetDC/ReleaseDC appropriately. The same goes for LockWindowUpdate and LockWindowUpdate(NULL).
Comment 8 Felipe Heidrich CLA 2011-12-20 10:07:37 EST
Steve, please see my previous comment.

*it proves the problem is not specific to the Tree*

Tree without columns is just like the Table (one window), and does not present the problem.

The ScrolledComposite + Canvas case is the same as the tree with columns (two windows), and presents the problem.
Comment 9 Felipe Heidrich CLA 2011-12-20 10:10:52 EST
Created attachment 208623 [details]
snippet showing the problem without Tree

Please run this Snippet,

It does not use Tree anywhere and has the same problem.
Once the window is up scroll the left panel horizontally.

Let me know if you can reproduce the problem with this snippet on your machine.

Thank you.
Comment 10 Steven Darnell CLA 2011-12-20 11:16:01 EST
I can reproduce the behavior with the scrolled composite snippet.

I noticed that clicking in the increment area around the thumb for the scrolled composite causes the background to improperly draw in the GLCanvas while this is not the case for the tree with columns. I assume that is because one is a pure SWT control and the other is based on a native control.
Comment 11 Thilo Bohr CLA 2013-04-10 09:03:26 EDT
I can reproduce the behavior when running the provided Snippets using a 3.8 Version of SWT (swt-win32-3816.dll) as well as a current swt-4.2.1-win32-win32-x86 (swt-win32-4234.dll) Version.
This bug unfortunately has not been touched a long time. Has anyone been able by any chance to fix the bug or find a suitable workaround?
Comment 12 Nate Jensen CLA 2015-07-07 18:25:21 EDT
We just encountered this problem too.  Only known workarounds are to turn off Aero or force repaints of the GLCanvas.  Would be nice if this could be fixed.
Comment 13 Nate Jensen CLA 2016-06-03 13:02:01 EDT
Tested on Eclipse 4.5.1 and it's still a problem when Aero is enabled.
Comment 14 mavami mavami CLA 2016-09-07 04:59:10 EDT
I was also facing the same issue with scrolling. ScrolledComposite left a trace on GLCanvas. Accidentally found one workaround: inside of ScrolledComposite I added transparent composite and there put all the other stuff. And the issue is gone. Maybe this will be helpfull. In my case it works great:

ScrolledComposite scrolledComposite = new ScrolledComposite(parent, SWT.V_SCROLL | SWT.H_SCROLL);
Composite composite = new Composite(scrolledComposite, SWT.NONE | SWT.TRANSPARENT);
 scrolledComposite.setContent(composite);
Comment 15 Eclipse Genie CLA 2020-06-17 14:26:03 EDT
This bug hasn't had any activity in quite some time. Maybe the problem got resolved, was a duplicate of something else, or became less pressing for some reason - or maybe it's still relevant but just hasn't been looked at yet. As such, we're closing this bug.

If you have further information on the current state of the bug, please add it and reopen this bug. The information can be, for example, that the problem still occurs, that you still want the feature, that more information is needed, or that the bug is (for whatever reason) no longer relevant.

--
The automated Eclipse Genie.