GNOME Bugzilla – Bug 759287
Canvas Tearing While in Rotated Canvas View
Last modified: 2018-01-10 03:00:06 UTC
Created attachment 317089 [details] Canvas looks tearing/destroyed/ruined/whatever First sorry for bad English... :D Canvas looks tearing/destroyed/ruined/whatever (look at attachment) Steps to reproduce: 1. Open an image without alpha channel (.jpeg) 2. Lower its opacity, make it transparent <-- this is kinda important to being able to reproduce 3. Create a new layer 4. 'Rotate' the canvas (using shift+space or keyboard assigned to it) 5. Use paint tools on the new layer Actual Result: Canvas looks 'teared/destroyed/ruined/whatever', but only in rotated canvas view. If I reset the canvas rotation, it back to normal and don't show any problem. Expected Result: Canvas act normally, just like when using Krita or MyPaint Temporary solution: Add an extra layer at the most back of the layer (layer without alpha channel or layer filled with color on 100% opacity) <-- this makes the 'canvas tearing' disappear LinuxMint 17 XCFE By the way, is it normal that the white grid appear?
Thanks for reporting! Trying to reproduce without luck so far... Made two layers: 1) bottom layer without alpha channel, any opacity between 0% and 100%. 2) top layer with solid color fill, opacity 100%. Rotated canvas. Tried painting. Can't see either white grid or destroyed canvas: http://i.imgur.com/9YfACQJ.png. I do vaguely recall seeing some sort of grid above rotated canvas about two years ago when canvas rotation was first introduced. But it'd be difficult for me to tell if that was original implementation in GIMP Painter or implementation in GIMP at the time. LinuxMint 17 was released 1.5 years ago. This could be some bug in Cairo that has been fixed since then. Let's see if someone can clarify this.
(In reply to Alexandre Prokoudine from comment #1) > Thanks for reporting! > > Trying to reproduce without luck so far... > > Made two layers: > > 1) bottom layer without alpha channel, any opacity between 0% and 100%. add the alpha channel to a red bottom layer and set opacity to 50% > 2) top layer with solid color fill, opacity 100% and paint on a transparent top layer, for example, but is enough to move the brush on it > > Rotated canvas. > > Tried painting. > > Can't see either white grid or destroyed canvas: Not always white, it depends on the image colors, but I can reproduce it. And I think it is a duplicate or related to https://bugzilla.gnome.org/show_bug.cgi?id=701415
Created attachment 317336 [details] [review] first attempt The attached patch is a first attempt to fix this problem. When there is a rotation it renders the projection over the checkers in a opaque group which is then painted to the window using the ADD operator. It requires to clear the window to black (0) because apparently the canvas padding color is painted even inside the image bounds, at least in some cases. It seems to work, I did not test the foreground selection mask and hi ppi screen scaling. I suspect that there is a simpler way to fix this problem chunking in transformed space, instead of image space, in gimp_display_shell_draw_image (app/display/gimpdisplayshell-draw.c), that way chunks would be always whole pixels wide/high and there would be no transparency/coverage mixing.
Created attachment 317405 [details] [review] Alternative approach The attached patch is a proof of concept of the alternative approach I had in mind. It does not deal with different X/Y image resolutions and when chunking is necessary it recursively splits the area in 4, but it shows that it is possible to simplify the rendering code without artifacts.
In any case we must fix this for 2.10. I still don't really understand what exactly is happening, but I haven't looked at this in quite a while. Can you quickly summarize what exactly the problem is?
Created attachment 337749 [details] [review] fixes artifacts moving brush outline on rotated canvas with transparency Here there are two problems: one is the 'grid'. The second is that when rendering rotated content, the source area required includes an excess that is currently painted more times when the exposed area is split in many rectangles. It works only when the content is fully transparent/opaque. IOW there is one big clip for the exposed area, but rendering in chunks requires one clip for chunk. The attached patch fixes this second problem, clipping in screen/canvas space each rectangle. Besides that, I'm not sure the code deals properly with images and displays both having resx != resy, it seems too simple, but I could be wrong.
Does the third patch obsolete the previous two?
N0, but none of them is complete so I'm going to mark them all needs-work
Adding a link to bug 701415 which is also about some canvas corruption when painting on a rotated canvas, though it doesn't look as bad in this other bug report. Still it may be the same issue or related.
*** Bug 701415 has been marked as a duplicate of this bug. ***
Massimo, do you think you would have some time to review your patches and finish them? :-)
You snooze, you lose, dude ;) Pushed a fix to master, based on Massimo's screen-space chunking patch: commit 8029508fbef8b2b5b3abd3be8a3fbb7d46654f86 Author: Ell <ell_se@yahoo.com> Date: Sat Dec 9 04:25:35 2017 -0500 Bug 759287 - Canvas Tearing While in Rotated Canvas View Based on a patch by Massimo. Move the entire image-space/screen-space transformation logic from gimp_display_shell_render() to gimp_display_shell_draw_image(), so that the former works entirely in image space, and do the chunking and clipping in screen-space, making sure that image-space chunks are never larger than GIMP_DISPLAY_RENDER_BUF_WIDTH x GIMP_DISPLAY_RENDER_BUF_HEIGHT, even when the window's scale factor is greater than 1. Add a GIMP_BRICK_WALL environment variable, which, when set, shows the screen-space chunk bounds. app/display/gimpdisplayshell-callbacks.c | 4 +++ app/display/gimpdisplayshell-draw.c | 145 ++++++++++++++++++++++++++++++++++++++++++++++++++-------------------------------- app/display/gimpdisplayshell-render.c | 212 ++++++++++++++++++++++++++---------------------------------------------------------------------------------------------- app/display/gimpdisplayshell-render.h | 3 +- 4 files changed, 140 insertions(+), 224 deletions(-)
Created attachment 366464 [details] Left: unrotated - Right: rotated Actually that's not fixed at all, unless there is another problem as well. This is very easy to reproduce on current master: - draw something - start rotating the canvas Result: you see the tearing happen even as you are rotating the canvas. It's like your lines are alive and spikes go and move on them while you rotate. ;p See attached image.
That would be commit 36258a671a04336260b1154128f8ff2cd9b85673 :) It's a trade-off between quality and speed (and not related to this bug).
Hmmm… Can't there be a better compromise? I find the quality quite horrible. But I am not drawing myself and Aryeom doesn't really use canvas rotation either, so maybe painters who do are ok with it (though I doubt it).
Created attachment 366565 [details] screenshot showing zig-zag edges (In reply to Jehan from comment #15) > Hmmm… Can't there be a better compromise? I find the quality quite horrible. > > But I am not drawing myself and Aryeom doesn't really use canvas rotation > either, so maybe painters who do are ok with it (though I doubt it). I do draw/paint (just a beginner), and I do use canvas rotation. I agree, the quality is not good (understatement). The attached screenshot shows black squiggly lines on a white background, single layer, no alpha channel, 100% opacity, 15-degree clockwise rotation, as displayed in default GIMP and also in my patched "CCE" version of GIMP. The artifacts from rotating the view ("View/Flip and Rotate") are obvious in default GIMP, but not in my patched "CCE", which is up-to-date with babl updated through July 2017, and GEGL/GIMP through November 8, 2017. So I'm guessing that whatever is causing the zig-zags might have been added some time after November 8, 2016, or else after July 2017 if there's any slim chance it could be babl-related.
Elle: could you run: > git revert 36258a671a04336260b1154128f8ff2cd9b85673 And see if that improves things on your side? Also does that make drawing much more slower when canvas is rotated?
(In reply to Jehan from comment #17) > Elle: could you run: > > > git revert 36258a671a04336260b1154128f8ff2cd9b85673 > > And see if that improves things on your side? Also does that make drawing > much more slower when canvas is rotated? Hi Jehan, I reverted the commit and recompiled, and that fixed the zig-zags. As far as "much more slower when canvas is rotated, no, the speed of painting seems about the same with or without canvas rotation, at least for the brush+settings that I tried.
Ok so I just took on myself to revert this commit. It was just too bad and really rotation of canvas was made useless. Ell: was this commit done for a specific bug in particular? I think we will have to find something else. What is the default filter used on cairo? Reading the enum list, it looks like CAIRO_FILTER_GOOD may be the next one to test, but maybe that is already the default. Or some other ways have to be found, which are less radical compromises. In the meantime, I re-close this bug report because any canvas tearing is now gone at least. commit 21cb905dad8e8ccb95a4a420293102a478b7638e (HEAD -> master, origin/master, origin/HEAD) Author: Jehan <jehan@girinstud.io> Date: Wed Jan 10 03:38:25 2018 +0100 Revert "app: use FAST filter when painting xfer surface" This reverts commit 36258a671a04336260b1154128f8ff2cd9b85673. This commit was making the rotated canvas rendering quite horrible to the point that I think it would make the canvas rotation feature barely usable. See bug 759287, comments 13 to 18. I think we will need to find other ways to accelerate rendering. Compromise on quality is possible, but I think that in this case, this was more than just a compromise. It was more like completely abandonning quality. We could even see the lines "spiking" while you were rotating! Like your drawing was alive! app/display/gimpdisplayshell-render.c | 1 - 1 file changed, 1 deletion(-)