> My guess is, that the dirty region tracking code gets messed up by > the Hline.
Confirmed the GGI_X_CLEAN-Macro contains a bug (I think, it is pretty had to understand) Diff attached, please validate before I commit. Rationale for the changes: Old code was: #define GGI_X_CLEAN(vis, _x, _y, _w, _h) do { \ if (priv->dirtytl.x >= _x && priv->dirtybr.x <= _x + _w-1) { \ ### If the to be cleaned region is at least as wide as the dirty region, ### it can possibly be used to clip the region down. if (priv->dirtytl.y >= _y && priv->dirtybr.y <= _y + _h-1) { \ ### If it completely conceals the dirty region, turn off the dirty region. ### further processing can be stopped here. priv->dirtytl.x = 1; priv->dirtybr.x = 0; break; } \ if ((priv->dirtybr.y < _y) || (priv->dirtytl.y > _y + _h-1)) break; \ ### If the region is completely outside of the dirty region (i.e. starts ### below it or stops above it, nothing happens. Stop processing. if ((priv->dirtybr.y < _y + _h-1) && (priv->dirtytl.y > _y)) break; \ ### Now here is the first bug. I think this is supposed to check, if ### the cleaned reagion is completely within the dirty region, in which ### case nothing can be done (it would split the region in two ### However it does check, that the cleaned region contains the dirty ### one. Correct code would IMHO be: ++if ((priv->dirtybr.y > _y + _h-1) && (priv->dirtytl.y < _y)) break; \ ### Mind the reversed comparisions. if (priv->dirtytl.y < _y) priv->dirtybr.y = _y; \ ### Now we want o check, if it overlaps at the top or the bottom. ### This is inaccurate IMHO. The line y is cleared, so we can set y-1. ++if (priv->dirtytl.y < _y) priv->dirtybr.y = _y-1; if (priv->dirtybr.y > _y + _h-1) priv->dirtytl.y = _y + _h-1; \ ### Same here. y+h-1 is the last line that is cleaned, so we can start ### one line below, i.e. ++if (priv->dirtybr.y > _y + _h-1) priv->dirtytl.y = _y + _h; break; \ ### is redundant here. We are in while(0), so we will autobreak anyway. } else if (priv->dirtytl.x >= _x && priv->dirtybr.x <= _x + _w-1) { \ ### Uh - ouch. Next bug I think. I suppose this section is supposed ### to check the same but snipping off at left and right. For that to ### work, we should check the y parameters. I.e. ++ } else if (priv->dirtytl.y >= _y && priv->dirtybr.y <= _y + _h-1) { \ if (priv->dirtytl.x >= _x && priv->dirtybr.x <= _x + _w-1) { \ priv->dirtytl.x = 1; priv->dirtybr.x = 0; break; } \ ### This is redundant, as the check in the area above would have catched it. if ((priv->dirtybr.x < _x) || (priv->dirtytl.x > _x + _w-1)) break; \ ### Check cleans left/right of dirty region. if ((priv->dirtybr.x < _x + _w-1) && (priv->dirtytl.x > _x)) break; \ # Check for completely contained region. Wrong like above. ++if ((priv->dirtybr.x > _x + _w-1) && (priv->dirtytl.x < _x)) break; if (priv->dirtytl.x < _x) priv->dirtybr.x = _x; \ if (priv->dirtybr.x > _x + _w-1) priv->dirtytl.x = _x + _w-1; \ # Comments like above leading to ++if (priv->dirtytl.x < _x) priv->dirtybr.x = _x-1; \ ++if (priv->dirtybr.x > _x + _w-1) priv->dirtytl.x = _x + _w; \ break; \ # redundant. }} while (0) I spent quite a while thinking this code through, and suppose I got it right. I am not quite sure about the last two ifs in each chain. I think one could use greater/less-or-equal in the comparisions as well, thus correctly handling regions that just touch the borders. I have tested these changes with my application, and it fixes the problems I reported. Could you please go over the code and my comments and have a look, if the fix is right? That stuff is pretty complex to think into, so I am not absolutely positive I didn't mis anything. If a few people confirm my thought, I will commit. CU, Andy -- = Andreas Beck | Email : <[EMAIL PROTECTED]> =
? bla Index: include/ggi/display/x.h =================================================================== RCS file: /cvsroot/ggi/ggi-core/libggi/include/ggi/display/x.h,v retrieving revision 1.3 diff -u -r1.3 x.h --- include/ggi/display/x.h 12 Jun 2002 03:53:59 -0000 1.3 +++ include/ggi/display/x.h 14 Dec 2002 15:01:25 -0000 @@ -208,18 +208,14 @@ if (priv->dirtytl.y >= _y && priv->dirtybr.y <= _y + _h-1) { \ priv->dirtytl.x = 1; priv->dirtybr.x = 0; break; } \ if ((priv->dirtybr.y < _y) || (priv->dirtytl.y > _y + _h-1)) break; \ - if ((priv->dirtybr.y < _y + _h-1) && (priv->dirtytl.y > _y)) break; \ - if (priv->dirtytl.y < _y) priv->dirtybr.y = _y; \ - if (priv->dirtybr.y > _y + _h-1) priv->dirtytl.y = _y + _h-1; \ - break; \ -} else if (priv->dirtytl.x >= _x && priv->dirtybr.x <= _x + _w-1) { \ - if (priv->dirtytl.x >= _x && priv->dirtybr.x <= _x + _w-1) { \ - priv->dirtytl.x = 1; priv->dirtybr.x = 0; break; } \ + if ((priv->dirtybr.y > _y + _h-1) && (priv->dirtytl.y < _y)) break; \ + if (priv->dirtytl.y < _y) priv->dirtybr.y = _y-1; \ + if (priv->dirtybr.y > _y + _h-1) priv->dirtytl.y = _y + _h; \ +} else if (priv->dirtytl.y >= _y && priv->dirtybr.y <= _y + _h-1) { \ if ((priv->dirtybr.x < _x) || (priv->dirtytl.x > _x + _w-1)) break; \ - if ((priv->dirtybr.x < _x + _w-1) && (priv->dirtytl.x > _x)) break; \ - if (priv->dirtytl.x < _x) priv->dirtybr.x = _x; \ - if (priv->dirtybr.x > _x + _w-1) priv->dirtytl.x = _x + _w-1; \ - break; \ + if ((priv->dirtybr.x > _x + _w-1) && (priv->dirtytl.x < _x)) break; \ + if (priv->dirtytl.x < _x) priv->dirtybr.x = _x-1; \ + if (priv->dirtybr.x > _x + _w-1) priv->dirtytl.x = _x + _w; \ }} while (0) #define GGI_X_SYNC(_vis) XFlush(GGIX_PRIV(_vis)->disp); #define GGI_X_MAYBE_SYNC(_vis) \