CVSROOT: /cvsroot/gnash Module name: gnash Changes by: Udo Giacomozzi <udog> 07/10/24 12:20:05
Modified files: . : ChangeLog server : dlist.cpp Log message: server/dlist.cpp: optimize add_invalidated_bounds() for masks (don't invalidate outside of masks) CVSWeb URLs: http://cvs.savannah.gnu.org/viewcvs/gnash/ChangeLog?cvsroot=gnash&r1=1.4682&r2=1.4683 http://cvs.savannah.gnu.org/viewcvs/gnash/server/dlist.cpp?cvsroot=gnash&r1=1.96&r2=1.97 Patches: Index: ChangeLog =================================================================== RCS file: /cvsroot/gnash/gnash/ChangeLog,v retrieving revision 1.4682 retrieving revision 1.4683 diff -u -b -r1.4682 -r1.4683 --- ChangeLog 24 Oct 2007 12:15:55 -0000 1.4682 +++ ChangeLog 24 Oct 2007 12:20:04 -0000 1.4683 @@ -2,6 +2,8 @@ * libgeometry/snappingrange.h: add routines for calculating intersections between SnappingRanges + * server/dlist.cpp: optimize add_invalidated_bounds() for + masks (don't invalidate outside of masks) 2007-10-24 Sandro Santilli <[EMAIL PROTECTED]> Index: server/dlist.cpp =================================================================== RCS file: /cvsroot/gnash/gnash/server/dlist.cpp,v retrieving revision 1.96 retrieving revision 1.97 diff -u -b -r1.96 -r1.97 --- server/dlist.cpp 17 Oct 2007 11:14:17 -0000 1.96 +++ server/dlist.cpp 24 Oct 2007 12:20:05 -0000 1.97 @@ -846,19 +846,131 @@ void DisplayList::add_invalidated_bounds(InvalidatedRanges& ranges, bool force) { - testInvariant(); + /* + This function generally has nothing else to do than calling the + add_invalidated_bounds() function of all items in the display list. + However, special optimization is included for masks, which makes it + look a bit more complicated. We want to avoid that a masked character + invalidates an area where the character is invisible because of it's + mask (which is quite common). For example, think of a large bitmap that + covers the entire stage and is masked by a very small circle in the + middle of the stage (ie. it's only visible there). Changes in the + bitmap sprite would invalidate the whole stage even if only the small + masked portion in the middle really needs to be drawn again. + + So, like display(), we keep a stack of masks. Instead of drawing the + mask we keep a separate list of InvalidatedRanges for the masks which + later are intersected with the masked characters' InvalidatedRanges. + + The code is much based on the display() function, so some references + in comments have been added for convenience. + + For a simpler implementation (that doesn't care about masks, but + still produces correct results) see CVS revision 1.96 + */ + + std::stack<int> clipDepthStack; // same method used in display() + std::stack<InvalidatedRanges> rangesStack; + bool drawing_mask = false; + iterator it = beginNonRemoved(_charsByDepth); for( iterator endIt = _charsByDepth.end(); it != endIt; ++it) { DisplayItem& dobj = *it; + #ifndef GNASH_USE_GC assert(dobj->get_ref_count() > 0); #endif // ndef GNASH_USE_GC + + + int depth = dobj->get_depth(); + // Discard useless masks + while (!clipDepthStack.empty() && (depth > clipDepthStack.top())) + { + clipDepthStack.pop(); + + // also add mask to ranges because mask itself may have changed +// ranges.add(rangesStack.top()); + + rangesStack.pop(); // disable_mask() equivalent + + } + + int clipDepth = dobj->get_clip_depth(); + // Push a new mask to the masks stack + if (clipDepth != character::noClipDepthValue) + { + clipDepthStack.push(clipDepth); + + drawing_mask = true; // begin_submit_mask equivalent + + if (rangesStack.empty()) + { + InvalidatedRanges item; + rangesStack.push(item); + } else { + rangesStack.push(rangesStack.top()); // copy the top mask + } + } + + // ==> display() equivalent + + if (drawing_mask) { + + // --> The child is part of a mask, so add ranges to our + // mask ranges stack + + assert(!rangesStack.empty()); + dobj->add_invalidated_bounds(rangesStack.top(), true); + + // need to call add_invalidated_bounds again because the previous + // call needs force==true. Changes to the mask itself may also require + // re-rendering of the mask area, so we have to add the mask itself + // to the global ranges, but this time with normal "force" value... + // As long the mask has not been invalidated and force==false this + // call won't modify the "ranges" list. dobj->add_invalidated_bounds(ranges, force); + + } else { + + if (rangesStack.empty()) { + + // --> normal case for unmasked characters + dobj->add_invalidated_bounds(ranges, force); + + } else { + + // --> character is masked, so intersect with "mask" + + // first get the ranges of the child in a separate list + InvalidatedRanges childRanges; + childRanges.inheritConfig(ranges); + + dobj->add_invalidated_bounds(childRanges, force); + + // then intersect ranges with topmost "mask" + childRanges.intersect(rangesStack.top()); + + // add result to the global ranges + ranges.add(childRanges); + } + } // not drawing mask + + // <== end of display() equivalent + + + // Mask "drawing" has finished + if (dobj->isMask()) + { + drawing_mask = false; // end_submit_mask equivalent + } + } + + } _______________________________________________ Gnash-commit mailing list Gnash-commit@gnu.org http://lists.gnu.org/mailman/listinfo/gnash-commit