Bug 324823

Summary: Black square instead of window's content
Product: [Plasma] kwin Reporter: Alexander <vo.zaeb>
Component: generalAssignee: KWin default assignee <kwin-bugs-null>
Status: RESOLVED FIXED    
Severity: normal CC: andysem, friesoft, gabriel.rilling, illumilore, matz, maxim.stargazer, maximilian.ammann, me, nico.duke.forever, osirisgothra, vmlinuz386
Priority: NOR Flags: thomas.luebking: ReviewRequest+
Version: 4.11.1   
Target Milestone: 5   
Platform: Arch Linux   
OS: Linux   
URL: https://git.reviewboard.kde.org/r/124591/
See Also: https://bugs.kde.org/show_bug.cgi?id=347638
Latest Commit: Version Fixed In: 5.4
Sentry Crash Report:
Attachments: qdbus output
qdbus org.kde.kwin /KWin supportInformation output
Less simple patch
printf debugging stuff
Adjusted not so simple patch

Description Alexander 2013-09-12 07:26:07 UTC
Hi, this happen after upgrade to 4.10 and still present in 4.11.1

Please see these examples:
http://www.youtube.com/watch?v=abQ3sBvtMa4
http://www.youtube.com/watch?v=ftEMB2NtgDM

Both examples are with ruby mine but I remember it had also happen with google chrome and system settings.

In short the bug appears when window's size increased to the whole screen but not maximized.

Reproducible: Always

Steps to Reproduce:
Please see the example videos



I am using OpenGL 3.1 with the raster graphic system but it is reproducible with all available settings.
Comment 1 Thomas Lübking 2013-09-12 08:08:10 UTC
please attach the output of "qdbus org.kde.kwin /KWin supportInformation" (with gl compositing running) as well as "glxinfo -l" and "xrandr -q"
Thanks
Comment 2 Martin Flöser 2013-09-12 14:03:47 UTC
5 EUR on NVIDIA :-)
Comment 3 Thomas Lübking 2013-09-12 17:45:11 UTC
Seeing the video, please also provide the output of "xprop" (the cursor turns into a cross to allow you to pick the window) on the window when it's black.
Comment 4 Alexander 2013-09-12 18:40:35 UTC
Hi, the cursor has turned to cross because the window wasn't maximized, so it is ok.

The outputs:
qdbus: http://paste.kde.org/p8f0da506/00983313/
glxinfo: http://paste.kde.org/p83a675d1/90097801/
xrandr: http://paste.kde.org/pbaeea66c/09863137/
xprop: http://paste.kde.org/p072daa7b/90100261/

There are a few more bugs that appered afrer upgrade to 4.10. When I close RM window it is laggy, window disappear like a slideshow (I have enabled kwin effect for closing windows, so they become opaque).

Another much more serious problem is related to hibernate/restore. I often do not reboot my PC for 5-10 days using hibernate instead. And now often after restore I see a black screen with some small flashing parts of the desktop. This could be fixed by switching to console and restart kwin.
Comment 5 Thomas Lübking 2013-09-12 19:47:32 UTC
(In reply to comment #4)
> Hi, the cursor has turned to cross because the window wasn't maximized, 

That's not what i mean, but it's neither important - you managed to get the xprop dump ;-)

> _NET_WM_STATE(ATOM) = _NET_WM_STATE_MAXIMIZED_VERT, _NET_WM_STATE_MAXIMIZED_HORZ

This says the window is maximized (but on the video it seemed the window turned black when it was NOT maximized)
Is this from the "black" or the "visible" window?

> There are a few more bugs that appered afrer upgrade to 4.10. 
Please to not collect bugs. Makes triaging them hell on earth.

> When I close
> RM window it is laggy, window disappear like a slideshow (I have enabled
> kwin effect for closing windows, so they become opaque).

For now, i assume this to be the same issue (the black window means that the driver could not assign a texture - that's never a good sign)

> Another much more serious problem is related to hibernate/restore.
This is bug #322975 - From the explanations there, i fear this is the driver (but have no idea what exposes it), though restarting KWin from VT1 has been disregarded as viable option there.

Please comment this and whether toggling compositing twice "fixes" the problem as well *there* (not here)

(In reply to comment #2)
> 5 EUR on NVIDIA :-)

Qt Graphics System: raster
Compositing is active
Compositing Type: OpenGL
OpenGL vendor string: NVIDIA Corporation
OpenGL renderer string: GeForce GTX 560 Ti/PCIe/SSE2
OpenGL version string: 4.3.0 NVIDIA 325.15
OpenGL shading language version string: 4.30 NVIDIA via Cg compiler
Driver: NVIDIA
Driver version: 325.15
GPU class: GF100
OpenGL version: 4.3
GLSL version: 4.30
Comment 6 Alexander 2013-09-13 07:00:23 UTC
Hi, it is from the visible window.

But is is not necessary that a black window could not be maximized. Just started RM, it is maximized and the content is black again. Sometimes it starts maximized but content is visible and turns black when I click the "restore" button.

xprop (maximized and black): http://paste.kde.org/pc8edc81a/13790546/

> Please to not collect bugs. Makes triaging them hell on earth.
Sure, just asked here to check if those are known problems.
Comment 7 Alexander 2013-09-13 07:53:54 UTC
I can now reproduce the bug, please take a look:
http://www.youtube.com/watch?v=8h70BCq25e0
Comment 8 Alexander 2013-09-13 07:57:28 UTC
Oops, sorry for the Russian lang,  I tried to switch application language to Eng and restart the systemsettings, but effects' names were still in Russian. Perhaps another bug :)

The effect I was playing with on the video called "Maximize", but you probably already guessed.
Comment 9 bastian löher 2013-11-14 10:35:48 UTC
Hi, I can also confirm this bug:

Ubuntu: 13.10                          
Qt: 4.8.4                                                                                                                          
KDE: 4.11.3                                                                                                                        
KWin: 4.11.3 
Nvidia driver: 319.60
X-Server: 1.14.3

xprop output on a black rendered xterm window (not maximized): http://pastebin.kde.org/pn82qa0pa
glxinfo: http://pastebin.kde.org/pdh7k5gsd
xrandr: http://pastebin.kde.org/pmbndbjd2
qdbus output could not be pasted on pastebin.kde.org (triggered spam filter). I will attach it as a file.

Note: Input in the window is accepted while it is black (i.e. xterm has written characters I have typed while it was black)

When does this occur? Mostly after wakeup or after unlocking the session.
It does not happen to all of the windows (most notably xterm, but not Konsole, happens to Thunderbird, but not Chrome, Skype is affected, but not Pidgin)

Ways to work around:
- Maximize, restore the black window
- Switch off/on compositing in kwin
- Logout/Login
- Reboot
Comment 10 bastian löher 2013-11-14 10:36:49 UTC
Created attachment 83556 [details]
qdbus output
Comment 11 Thomas Lübking 2013-11-21 11:56:35 UTC
*** Bug 327884 has been marked as a duplicate of this bug. ***
Comment 12 Thomas Lübking 2013-12-24 00:21:50 UTC
*** Bug 329179 has been marked as a duplicate of this bug. ***
Comment 13 Thomas Lübking 2013-12-24 09:53:04 UTC
*** Bug 329179 has been marked as a duplicate of this bug. ***
Comment 14 Max A. 2014-03-13 20:57:43 UTC
Can confirm this bug, happens for me too. 

Qt Graphics System: nativ
Compositing Type: OpenGL 2.0
OpenGL vendor string: NVIDIA Corporation
OpenGL renderer string: GeForce GTX 560 Ti/PCIe/SSE2
OpenGL core profile version string: 4.3.0 NVIDIA 334.21
OpenGL core profile shading language version string: 4.30 NVIDIA via Cg compiler
OpenGL core profile context flags: (none)
OpenGL core profile profile mask: core profile
OpenGL core profile extensions:
OpenGL version string: 4.4.0 NVIDIA 334.21
OpenGL shading language version string: 4.40 NVIDIA via Cg compiler
NVIDIA driver version: 334.21
Comment 15 Max Sydorenko 2014-11-03 00:21:11 UTC
Created attachment 89411 [details]
qdbus org.kde.kwin /KWin supportInformation   output

I want to confirm this bug also. 
qdbus debug output attached.
Nvidia, proprietary driver.
Bug is observed only when "Maximize" Kwin effect is turned on.
Can I somehow help to pinpoint, what exactly is broken in proprietary driver, that causes this behaviour? So we can fill a bugreport on nvidia forum or whatever they have.
Comment 16 Michael Matz 2015-07-20 02:06:40 UTC
This problem plagued compiz as well for a time, until nvidia took a look at GLX usage.
Their finding is here: https://bugs.launchpad.net/ubuntu/+source/compiz/+bug/1072206/comments/63

Basically it boils down that two GLX pixmaps via glXCreatePixmap are created from the
same drawable, which isn't working in the nvidia driver, i.e. both pixmaps are actually used
without an intervening glXDestroyPixmap.

I've noticed this problem with plasma5, kwin 5.3.2, nvidia driver.

I have looked a bit at current kwin_x11 code (git bc45c61e), and haven't found immediately 
where that would happen.  But the whole crossFadePrevious handling (with possibly doing that
via ->texture() on previousWindowPixmap results) looks like such things might happen.
At least the Maximize effect is the only one using CrossFadePrevious.

Maybe someone knowing that code better sees quicker where the problem is.
Comment 17 Martin Flöser 2015-07-20 05:56:46 UTC
(In reply to Michael Matz from comment #16)
> Basically it boils down that two GLX pixmaps via glXCreatePixmap are created
> from the
> same drawable, which isn't working in the nvidia driver, i.e. both pixmaps
> are actually used
> without an intervening glXDestroyPixmap.

The description in the linked bug report shouldn't happen inside KWin - also not with crossfading. The basic idea behind the cross fading is that it is for different pixmaps, in particular of different sizes. So the "while the window's pixmap hasn't changed" condition should not be hit in KWin.

Also the cross fading mechanism itself should ensure that the problem cannot be hit as it reuses the "old" pixmap till a new one is created. So if the driver fails giving us a new one, we will continue to use the old one.

Of course I don't want to throw away the possibility that there are conditions where it could be hit due to bugs. If that's the case we need a very good test case for the situation.

If in deed the cross fading mechanism is causing the problem on NVIDIA we need to turn it into a driver capability and disable it for NVIDIA - this would no longer happen for 4.11 branch, though.
Comment 18 Thomas Lübking 2015-07-20 08:07:01 UTC
Can you 
a) reproduce this somewhat reliably
b) try a patch?

ftr:
::plainResize() in geometry.cpp has a semi-uncoditional discardWindowPixmap() which is reached even if s == geom.size() what happens when at least when the decoration is re/created, ie. we actually can discard the pixmap (and take a new one) on the same drawable size.
Comment 19 Michael Matz 2015-07-20 10:05:47 UTC
(In reply to Thomas Lübking from comment #18)
> Can you 
> a) reproduce this somewhat reliably

Yes, I have the blackness effect almost always when maximizing a window
(with the maximize effect).  It doesn't happen always, so it is racy, but it happens perhaps 9 out
of 10 times.

> b) try a patch?

Yes.
Comment 20 Thomas Lübking 2015-07-20 13:53:30 UTC
*Not* tested in any way:
---------------------------

diff --git a/geometry.cpp b/geometry.cpp
index 9876477..8ad4820 100644
--- a/geometry.cpp
+++ b/geometry.cpp
@@ -1902,6 +1902,7 @@ void Client::setGeometry(int x, int y, int w, int h, ForceGeometry_t force)
     // Such code is wrong and should be changed to handle the case when the window is shaded,
     // for example using Client::clientSize()
 
+    QSize oldClientSize = client_size;
     if (shade_geometry_change)
         ; // nothing
     else if (isShade()) {
@@ -1970,7 +1971,8 @@ void Client::setGeometry(int x, int y, int w, int h, ForceGeometry_t force)
     // - maximize mode is changed to MaximizeRestore, when size unchanged
     //   which can happen when untabbing maximized windows
     if (resized) {
-        discardWindowPixmap();
+        if (oldClientSize != client_size)
+            discardWindowPixmap();
         emit geometryShapeChanged(this, geom_before_block);
     }
     const QRect deco_rect = visibleRect();
@@ -1990,6 +1992,7 @@ void Client::setGeometry(int x, int y, int w, int h, ForceGeometry_t force)
 void Client::plainResize(int w, int h, ForceGeometry_t force)
 {
     // this code is also duplicated in Client::setGeometry(), and it's also commented there
+    QSize oldClientSize = client_size;
     if (shade_geometry_change)
         ; // nothing
     else if (isShade()) {
@@ -2034,7 +2037,8 @@ void Client::plainResize(int w, int h, ForceGeometry_t force)
     updateWindowRules(Rules::Position|Rules::Size);
     screens()->setCurrent(this);
     workspace()->updateStackingOrder();
-    discardWindowPixmap();
+    if (oldClientSize != client_size)
+        discardWindowPixmap();
     emit geometryShapeChanged(this, geom_before_block);
     const QRect deco_rect = visibleRect();
     addLayerRepaint(deco_rect_before_block);
Comment 21 Thomas Lübking 2015-07-20 14:27:11 UTC
Tested, bad patch - don't try!
(leaves invalid textures - smells like there is a problem in this context, though)
Comment 22 Thomas Lübking 2015-07-21 06:00:45 UTC
Created attachment 93677 [details]
Less simple patch

Little more complex patch ATTEMPT, which should however not falsely stall updates (problem was pending size changes being ignored) - and print when it newly skips a pixmap discard.
Comment 23 Michael Matz 2015-07-26 21:05:35 UTC
So, finally came to trying patch from comment #22, on top of tag v5.3.2 of kwin.git.
The black window bug after the maximizing effect remain, but the debug message added
by the patch does not trigger.  Something else in the debug output is interesting, though.
When the buggy behaviour doesn't happen (it doesn't always when maximizing), the debug
output contains some messages ala:

kwin_core: 0x20004: Usage warning: Generic vertex attribute array 1 uses a pointer with a small value (0x0x370). Is this intended to be used as an offset into a buffer object?
kwin_core: 0x20084: Texture state usage warning: Texture 39 is base level inconsistent. Check texture size.

Once the effect is finished debug output stops.  But if the buggy behaviour happens,
i.e. if the window content becomes black during maximizing effect and remains black
when it's finished, then the "texture state usage warning" debug output keeps repeating,
even after the effect is finished.  It keeps showing up, until I maximize/restore the window
so often until the real content shows again, instead of the black one.

The texture number itself changes from occurence to occurence of the bug, but remains
the same as long as the bug is currently happening, i.e. as long as one window is in
the buggy black state.

The text of the message is an openGL error message (output via glDebugMessageCallback).

So, somewhere there is a difference in kwin behaviour between when the bug happens
(something retries to do something but never succeeds), versus when it doesn't happen.
I haven't yet figured out what "something" here is.
Comment 24 Michael Matz 2015-07-26 21:11:05 UTC
FWIW: the added debug message from the patch ("SKIPPED discard ...") _does_ happen when
I resize a window (if in buggy state or not) by the window decoration border.  It doesn't happen
during the maximize effect itself.
Comment 25 Michael Matz 2015-07-27 02:50:57 UTC
Created attachment 93755 [details]
printf debugging stuff

A patch adding some qDebugs to various interesting glX call sites, so one understand what
I'm going to talk about in the next comment.
Comment 26 Michael Matz 2015-07-27 03:33:10 UTC
So, I've added some qDebugs and found something hinting at the problem I think.  With the 
patch above, when constantly maximizing and restoring the same window, the output
normally looks like so:

-------------------------------
# some initial stuff, now maximizing ...
# the following is WindowPixmap id, size, clientpos, toplevel frameid
WindowPixmap::create  104857803 QSize(1920, 1174) QRect(0,22 1920x1152) 10485768
glXCreatePixmap(  104857803  ) ==  104857762
glXBindTexImageEXT  104857762
glXReleaseTexImageEXT  104857758
glXDestroyPixmap  104857758
~WindowPixmap  104857759

# now restoring
WindowPixmap::create  104857811 QSize(1000, 914) QRect(4,26 992x884) 104857681
glXCreatePixmap(  104857811  ) ==  104857804
glXBindTexImageEXT  104857804
glXReleaseTexImageEXT  104857762
glXDestroyPixmap  104857762
~WindowPixmap  104857803
-------------------------------

So, as can be expected, when maximizing a new pixmap is created for the same toplevel
window (of the larger size), then a GLX pixmap is created from that, it's bound, then drawing 
and animation takes places, and when finished the old GLX pixmap and window pixmap are destroyed (e.g. in the above when restoring the destroyed windowpixmap 104857803 is
the one from the maximization before).

Reverse happens when restoring.  So, when constantly maximizing and restoring the pattern
is easy to see: a ::create call with the large size, some pixmap creation/destroying, and
and ::create call with the smaller size, some more pixmap stuff.

Now, when the bug happens it is always the case that there are _two_ WindowPixmap::create
calls with the _same size_ but different clientpos/clientsize (i.e. only the m_contentsRect changes, not the pixmapSize).  Like in the following, it starts with the very first setup
of the pixmaps for the window in question (in normal size, and no former pixmaps), then I did 
one maximization, the bug happened, and I did one restoring and the bug went hiding (i.e.
I was lucky to exhibit the bug nicely):

---------------------------------
WindowPixmap::create  104857757 QSize(1000, 914) QRect(4,26 992x884) 104857675
glXCreatePixmap(  104857757  ) ==  104857756
glXBindTexImageEXT  104857756

# now I maximized
WindowPixmap::create  104857803 QSize(1920, 1174) QRect(4,26 1912x1144) 104857675
glXCreatePixmap(  104857803  ) ==  104857762
glXBindTexImageEXT  104857762
glXReleaseTexImageEXT  104857756
glXDestroyPixmap  104857756
~WindowPixmap  104857757
WindowPixmap::create  104857807 QSize(1920, 1174) QRect(0,22 1920x1152) 104857675
glXCreatePixmap(  104857807  ) ==  104857804
glXBindTexImageEXT  104857804
glXReleaseTexImageEXT  104857762
glXDestroyPixmap  104857762
~WindowPixmap  104857803

# after this the window content was black

# then I restored again, and I was lucky enough to see the windows content again
WindowPixmap::create  104857917 QSize(1000, 914) QRect(4,26 992x884) 104857675
glXCreatePixmap(  104857917  ) ==  104857808
glXBindTexImageEXT  104857808
glXReleaseTexImageEXT  104857804
glXDestroyPixmap  104857804
~WindowPixmap  104857807
----------------------------------------

So, to recollect, for one maximization there are two WindowPixmaps created,
both of size 1920x1174, but once for contents 4,26@1912x1144, and once at 0,22@1920x1152.

The contentRect size differences are 8x8 and the position differences are 4x4, so I guess
the difference is, that once the borders are included, and once they aren't.  It is also
always the case that when the bug happens, that the first of the two ::create calls
shows the clientPos still at the one before (with the clientSize appropriately adjusted),
and the second one has the final clientPos for the operation in question (0,22 for my
decorations when maximizing).

Now comes the guessing part: the geometry of the various data structures in kwin
is changed in several steps, e.g. first toplevel, then pixmaps, then clientRect, then removing borders when maximizing, then updating clientRect again, but no changes to the X drawable
anymore.  I also guess during this there are multiple events fired that would result in
rendering the window.  Now if such rendering would happen while the pixmaps and other
X11 drawables are already in their final state, but a clientRect adjustment would result in
another drawing request, then the newly created GLX pixmap would indeed refer to a X
pixmap that still was created from the same drawable (it does have a different index, but the
underlying drawable is the same, like in the bug report about compiz I linked); and in nvidia
the result would be like observed.

I've tried to confirm this speculation with more qDebugs in setGeometry, but haven't 
pinpointed it yet.  I have something like this in my notes:
-----------------------------
# XXXXXXXX here the problem starts:
setGeometry  QRect(0,0 1920x1174)  for  'ID: 58720413 ;WMCLASS: "konqueror" : "k
setGeometry  QRect(0,0 1920x1174)  for  'ID: 58720413 ;WMCLASS: "konqueror" : "k
# so multiple setGeometry calls, resulting in one halfway painting:
WindowPixmap::create  109052237 QSize(1920, 1174) QRect(4,26 1912x1144) 10905197
glXCreatePixmap(  109052237  ) ==  109052228
glXBindTexImageEXT  109052228
# then more superfluous setGeometry calls ...
setGeometry  QRect(0,0 1920x1174)  for  'ID: 58720413 ;WMCLASS: "konqueror" : "k
setGeometry  QRect(0,0 1920x1174)  for  'ID: 58720413 ;WMCLASS: "konqueror" : "k
setGeometry  QRect(0,0 1920x1174)  for  'ID: 58720413 ;WMCLASS: "konqueror" : "k
# ... now the rest of the already started painting:
glXReleaseTexImageEXT  109052219
glXDestroyPixmap  109052219
~WindowPixmap  109052227
# Ugh, and now another painting attempt with same size:
WindowPixmap::create  109052241 QSize(1920, 1174) QRect(0,22 1920x1152) 10905197
glXCreatePixmap(  109052241  ) ==  109052238
glXBindTexImageEXT  109052238
glXReleaseTexImageEXT  109052228
glXDestroyPixmap  109052228
~WindowPixmap  109052237
----------------------------------------------

that additional output was with:

diff --git a/geometry.cpp b/geometry.cpp
index a204d64..26cd43c 100644
--- a/geometry.cpp
+++ b/geometry.cpp
@@ -1882,6 +1881,7 @@ void Client::setGeometry(int x, int y, int w, int h, ForceGeometry_t force)
             pending_geometry_update = PendingGeometryNormal;
         return;
     }
+    qDebug() << "setGeometry " << g << " for " << this;
     bool resized = (geom_before_block.size() != geom.size() || pending_geometry_update == pendingGeometryForced);
     if (resized) {
         resizeDecoration();
Comment 27 Martin Flöser 2015-07-27 09:27:28 UTC
Thanks for the great investigation!
Comment 28 Thomas Lübking 2015-07-27 11:25:47 UTC
It's easily possible that the deco border change is the ultimate trigger (run "breeze-settings5" and check "display borders for maximized windows" in the "window decoration" page to verify this), but your debug out doesn't look that surprising :-(

NOTICE, that your last "setGeometry" call does not imply something really happens - geometry updates may still be blocked.

Here's what it looks to me:

> # XXXXXXXX here the problem starts:
> setGeometry  QRect(0,0 1920x1174)  for  'ID: 58720413 ;WMCLASS: "konqueror" : "k
> setGeometry  QRect(0,0 1920x1174)  for  'ID: 58720413 ;WMCLASS: "konqueror" : "k
> # so multiple setGeometry calls, resulting in one halfway painting:
> WindowPixmap::create  109052237 QSize(1920, 1174) QRect(4,26 1912x1144) 10905197
> glXCreatePixmap(  109052237  ) ==  109052228
> glXBindTexImageEXT  109052228

One of the last setGeometry calls effectively changed the size of the decorated client window, the pixmap needs to be (re)-created.
::setGeometry() being called from various positions isn't that uncommon, therefore the entire geomerty blocking thing.

Notably see the client rect size: "QRect(4,26 1912x1144)"

> # then more superfluous setGeometry calls ...
> setGeometry  QRect(0,0 1920x1174)  for  'ID: 58720413 ;WMCLASS: "konqueror" : "k
> setGeometry  QRect(0,0 1920x1174)  for  'ID: 58720413 ;WMCLASS: "konqueror" : "k
> setGeometry  QRect(0,0 1920x1174)  for  'ID: 58720413 ;WMCLASS: "konqueror" : "k

I assume that these are caused by the deco border resize. The entire window size does not change due to this, but the decorated client will (as the borders are removed, it gains room to grow a bit)

> # ... now the rest of the already started painting:
> glXReleaseTexImageEXT  109052219
> glXDestroyPixmap  109052219
> ~WindowPixmap  109052227

The old previous client pixmap is released, because (hopefully) the client size changed by the deco borders being removed - next we need a new pixmap and the new current becomes the previous one.

> # Ugh, and now another painting attempt with same size:
> WindowPixmap::create  109052241 QSize(1920, 1174) QRect(0,22 1920x1152) 10905197
> glXCreatePixmap(  109052241  ) ==  109052238
> glXBindTexImageEXT  109052238

There it is.
Notably see the NEW client rect size: "QRect(0,22 1920x1152)" (was 4,26 1912x1144)

The client size is (should be) irrelevant in this regard, the client texture size is the one of the redirected window _inside_ the decorated client.

Here it perhaps gets interesting:

> glXReleaseTexImageEXT  109052228
> glXDestroyPixmap  109052228
> ~WindowPixmap  109052237

The previous pixmap is destroyed - if you slow down the maximization effect (animation speed in "kcmshell5 kwincompositing"), you should notice that this happens NOT before the crossfading is supposed to have ended.
Comment 29 Michael Matz 2015-08-01 18:18:27 UTC
(In reply to Thomas Lübking from comment #28)
> It's easily possible that the deco border change is the ultimate trigger
> (run "breeze-settings5" and check "display borders for maximized windows" in
> the "window decoration" page to verify this),

The way borders are enabled/disabled when restoring/maximizing is one or the trigger
probably.  Because I can't reproduce the problem with the breeze windows deco at all, only
with Plastik (no matter the "display borders" setting for breeze).

> NOTICE, that your last "setGeometry" call does not imply something really
> happens - geometry updates may still be blocked.

Yes, I know, but whenever there's a WindowPixmap::create() call after a setGeometry,
that hints at the fact that for that setGeometry call the updates weren't blocked anymore.

Let me try to point to what I think the problem with the GLX pixmaps is (maybe we're saying
the same thing already, but just to clear up my own mind :) ):

> > # XXXXXXXX here the problem starts:
> > setGeometry  QRect(0,0 1920x1174)  for  'ID: 58720413 ;WMCLASS: "konqueror" : "k
> > setGeometry  QRect(0,0 1920x1174)  for  'ID: 58720413 ;WMCLASS: "konqueror" : "k
> > # so multiple setGeometry calls, resulting in one halfway painting:
> > WindowPixmap::create  109052237 QSize(1920, 1174) QRect(4,26 1912x1144) 10905197
> > glXCreatePixmap(  109052237  ) ==  109052228
> > glXBindTexImageEXT  109052228

(Reducing the IDs to the last three digits)  So one of these setGeometry calls resulted
in repainting (so the geom changes weren't blocked), and hence
we created a GLX pixmap 228 from a drawable 237 (for toplevel 197).
At this point (from before the resize) we still have a drawable 227 and GLX pixmap 219
(for different sizes, so it's really a different drawable and pixmap).

> > # then more superfluous setGeometry calls ...
> > setGeometry  QRect(0,0 1920x1174)  for  'ID: 58720413 ;WMCLASS: "konqueror" : "k
> > setGeometry  QRect(0,0 1920x1174)  for  'ID: 58720413 ;WMCLASS: "konqueror" : "k
> > setGeometry  QRect(0,0 1920x1174)  for  'ID: 58720413 ;WMCLASS: "konqueror" : "k
> 
> I assume that these are caused by the deco border resize. The entire window
> size does not change due to this, but the decorated client will (as the
> borders are removed, it gains room to grow a bit)

Right.  So this will change the client size, but not the size (or other attributes)
of the underlying drawable.  Then what follows is:

In one thread of program flow the GLX and windowpixmap handling continues,
we just created 228 and 237 above and now we continue on and destroy the old
pixmap (219) and drawable (227):

> > # ... now the rest of the already started painting:
> > glXReleaseTexImageEXT  109052219
> > glXDestroyPixmap  109052219
> > ~WindowPixmap  109052227

Note how we still have the 228 and 237 objects internally referring to the toplevel.
One of the above later setGeometry calls (or something else) activates the whole
create windowpixmap and GLX pixmap business again, now with changed (and final)
client rect size, but same drawable size:

> > # Ugh, and now another painting attempt with same size:
> > WindowPixmap::create  109052241 QSize(1920, 1174) QRect(0,22 1920x1152) 10905197
> > glXCreatePixmap(  109052241  ) ==  109052238
> > glXBindTexImageEXT  109052238

So we now created another windowpixmap 241 (for toplevel 197), referring to the same
underlying window with unchanged properties from when 237 was created above.
From that we generate GLX pixmap 238, et voila, we now have two GLX pixmaps
referring (indirectly via the windowpixmaps 237 and 241) to the same drawable
(it is the same because no attributes changed between creating one windowpixmap and the
other).

From the description of the NVIDIA guy in the compiz bug, this creation of the second
GLX pixmap is already the one that's breaking.  Even though we destroy the older pixmap
and GLX pixmap right away:

> > glXReleaseTexImageEXT  109052228
> > glXDestroyPixmap  109052228
> > ~WindowPixmap  109052237

... the newer GLX pixmap (238) is still the invalidly constructed one, and the one we continue
to use to do the drawing.

Perhaps this can be rectified by first destroying the GLX pixmap and only then creating
a new one, but this probably isn't possible in the current design with the previous
pixmap and current pixmap.

Alternatively the situation could be detected that if the drawable didn't really change
from when the GLX pixmap was created then no new one would be generated.
Comment 30 Thomas Lübking 2015-08-01 22:36:07 UTC
Created attachment 93837 [details]
Adjusted not so simple patch

> only with Plastik (no matter the "display borders" setting for breeze).

Ahhhhhh... easily reproducable.
Please try the updated patch.
Comment 31 Michael Matz 2015-08-02 00:03:44 UTC
(In reply to Thomas Lübking from comment #30)
> > only with Plastik (no matter the "display borders" setting for breeze).
> 
> Ahhhhhh... easily reproducable.
> Please try the updated patch.

Hah!  I now do see some 'SKIPPED discard' messages when I continuously maximize/restore
windows, and no further multiple WindowPixmap::create calls with the same QSize (and only
different client QRect) in a row.  The effects of that (i.e. the black contents) are also gone
(incidentally showing that it's indeed the multiple GLX pixmaps from same drawable that
cause this effect).

Excellent, thanks.
Comment 32 Thomas Lübking 2015-08-02 12:50:54 UTC
Ok, many thanks for your testing and debugging efforts =)

There'll be something more to this, the significant (in this context, I believe) difference between aurorae (what also powers plastik) and breeze is that former utilizes a GL context of its own, so we have a pixmap update for a drawable that is itself a GL context - an I could assume that this might lack a sync between the context switches (but it's only a guess)
Comment 33 Michael Matz 2015-08-02 21:57:56 UTC
(In reply to Thomas Lübking from comment #32)
> Ok, many thanks for your testing and debugging efforts =)
> 
> There'll be something more to this, the significant (in this context, I
> believe) difference between aurorae (what also powers plastik) and breeze is
> that former utilizes a GL context of its own,

Yeah, right, I noticed this later as well, when reading code (trying to find out why
aurorae needs 70 to 100 MB more memory than breeze in my situation ;-) At least part of
it is because of the QOpenGLFramebufferObject objects in the decoration).  As it seems
mostly to be used for drawing the shadow, and breeze can do the same without (using a much
smaller image) I wonder if that aurorae code isn't meanwhile obsolete from pre-compositing
times.

> so we have a pixmap update for
> a drawable that is itself a GL context - an I could assume that this might
> lack a sync between the context switches (but it's only a guess)

Yeah, possibly, but I think the general idea of not discarding a pixmap if the attributes
haven't changed, as in your patch, is a good thing nonetheless.
Comment 34 Thomas Lübking 2015-08-14 23:58:48 UTC
Git commit eb71b47db430bd04b859e49e0415192ae7114a25 by Thomas Lübking.
Committed on 14/08/2015 at 23:34.
Pushed by luebking into branch 'Plasma/5.4'.

only discard pixmaps when the XCB Window resized

Causes invalid textures on the nvidia blob
when referencing textures for crossfading
eg. during maximization
REVIEW: 124591
FIXED-IN: 5.4

M  +6    -2    geometry.cpp

http://commits.kde.org/kwin/eb71b47db430bd04b859e49e0415192ae7114a25
Comment 35 Thomas Lübking 2015-11-01 08:45:01 UTC
*** Bug 347425 has been marked as a duplicate of this bug. ***
Comment 36 Martin Flöser 2016-09-02 10:22:23 UTC
*** Bug 347638 has been marked as a duplicate of this bug. ***