# HG changeset patch # Parent 80db2a64985773c27bec5ade623c4a5aee5f18ad # User Chris Lord Bug 704575 - Union dirty rects instead of painting all of them. r=kats In bug #703821 we disabled the squashing of multiple draw events, as it caused corruption due to the dirty rects being ignored. Re-enable it, and union the dirty rectangles to avoid this corruption. diff --git a/widget/src/android/nsAppShell.cpp b/widget/src/android/nsAppShell.cpp --- a/widget/src/android/nsAppShell.cpp +++ b/widget/src/android/nsAppShell.cpp @@ -207,69 +207,85 @@ nsAppShell::ProcessNextNativeEvent(bool { EVLOG("nsAppShell::ProcessNextNativeEvent %d", mayWait); nsAutoPtr curEvent; AndroidGeckoEvent *nextEvent; { MutexAutoLock lock(mCondLock); - curEvent = GetNextEvent(); + curEvent = PopNextEvent(); if (!curEvent && mayWait) { // hmm, should we really hardcode this 10s? #if defined(DEBUG_ANDROID_EVENTS) PRTime t0, t1; EVLOG("nsAppShell: waiting on mQueueCond"); t0 = PR_Now(); mQueueCond.Wait(PR_MillisecondsToInterval(10000)); t1 = PR_Now(); EVLOG("nsAppShell: wait done, waited %d ms", (int)(t1-t0)/1000); #else mQueueCond.Wait(); #endif - curEvent = GetNextEvent(); + curEvent = PopNextEvent(); } } if (!curEvent) return false; // Combine subsequent events of the same type nextEvent = PeekNextEvent(); while (nextEvent) { int curType = curEvent->Type(); int nextType = nextEvent->Type(); - // Do not skip draw events if the Java compositor is in use, since the Java compositor - // updates only the rect that changed - thus we will lose updates. -#ifndef MOZ_JAVA_COMPOSITOR - while (nextType == AndroidGeckoEvent::DRAW && + while (nextType == AndroidGeckoEvent::DRAW && mLastDrawEvent && mNumDraws > 1) { // skip this draw, since there's a later one already in the queue.. this will let us // deal with sequences that look like: // MOVE DRAW MOVE DRAW MOVE DRAW // and end up with just // MOVE DRAW // when we process all the events. - RemoveNextEvent(); + + // Combine the next draw event's rect with the last one in the queue + const nsIntRect& nextRect = nextEvent->Rect(); + const nsIntRect& lastRect = mLastDrawEvent->Rect(); + int combinedArea = (lastRect.width * lastRect.height) + + (nextRect.width * nextRect.height); + + nsIntRect combinedRect = lastRect.Union(nextRect); + mLastDrawEvent->Init(AndroidGeckoEvent::DRAW, combinedRect); + + // XXX We may want to consider using regions instead of rectangles. + // Print an error if we're upload a lot more than we would + // if we handled this as two separate events. + int boundsArea = combinedRect.width * combinedRect.height; + if (boundsArea > combinedArea * 8) + ALOG("nsAppShell::ProcessNextNativeEvent: " + "Area of bounds greatly exceeds combined area: %d > %d", + boundsArea, combinedArea); + + // Remove the next draw event + PopNextEvent(); delete nextEvent; #if defined(DEBUG_ANDROID_EVENTS) ALOG("# Removing DRAW event (%d outstanding)", mNumDraws); #endif nextEvent = PeekNextEvent(); nextType = nextEvent->Type(); } -#endif // If the next type of event isn't the same as the current type, // we don't coalesce. if (nextType != curType) break; // Can only coalesce motion move events, for motion events if (curType != AndroidGeckoEvent::MOTION_EVENT) @@ -278,18 +294,17 @@ nsAppShell::ProcessNextNativeEvent(bool if (!(curEvent->Action() == AndroidMotionEvent::ACTION_MOVE && nextEvent->Action() == AndroidMotionEvent::ACTION_MOVE)) break; #if defined(DEBUG_ANDROID_EVENTS) ALOG("# Removing % 2d event", curType); #endif - RemoveNextEvent(); - curEvent = nextEvent; + curEvent = PopNextEvent(); nextEvent = PeekNextEvent(); } EVLOG("nsAppShell: event %p %d [ndraws %d]", (void*)curEvent.get(), curEvent->Type(), mNumDraws); switch (curEvent->Type()) { case AndroidGeckoEvent::NATIVE_POKE: NativeEventCallback(); @@ -431,25 +446,26 @@ nsAppShell::ProcessNextNativeEvent(bool void nsAppShell::ResendLastResizeEvent(nsWindow* aDest) { if (gLastSizeChange) { nsWindow::OnGlobalAndroidEvent(gLastSizeChange); } } AndroidGeckoEvent* -nsAppShell::GetNextEvent() +nsAppShell::PopNextEvent() { AndroidGeckoEvent *ae = nsnull; MutexAutoLock lock(mQueueLock); if (mEventQueue.Length()) { ae = mEventQueue[0]; mEventQueue.RemoveElementAt(0); if (ae->Type() == AndroidGeckoEvent::DRAW) { - mNumDraws--; + if (--mNumDraws == 0) + mLastDrawEvent = nsnull; } } return ae; } AndroidGeckoEvent* nsAppShell::PeekNextEvent() @@ -481,36 +497,23 @@ nsAppShell::PostEvent(AndroidGeckoEvent } } } else { mEventQueue.AppendElement(ae); } if (ae->Type() == AndroidGeckoEvent::DRAW) { mNumDraws++; + mLastDrawEvent = ae; } } NotifyNativeEvent(); } void -nsAppShell::RemoveNextEvent() -{ - AndroidGeckoEvent *ae = nsnull; - MutexAutoLock lock(mQueueLock); - if (mEventQueue.Length()) { - ae = mEventQueue[0]; - mEventQueue.RemoveElementAt(0); - if (ae->Type() == AndroidGeckoEvent::DRAW) { - mNumDraws--; - } - } -} - -void nsAppShell::OnResume() { } nsresult nsAppShell::AddObserver(const nsAString &aObserverKey, nsIObserver *aObserver) { NS_ASSERTION(aObserver != nsnull, "nsAppShell::AddObserver: aObserver is null!"); diff --git a/widget/src/android/nsAppShell.h b/widget/src/android/nsAppShell.h --- a/widget/src/android/nsAppShell.h +++ b/widget/src/android/nsAppShell.h @@ -71,34 +71,34 @@ public: nsresult Init(); void NotifyNativeEvent(); virtual bool ProcessNextNativeEvent(bool mayWait); void PostEvent(mozilla::AndroidGeckoEvent *event); - void RemoveNextEvent(); void OnResume(); nsresult AddObserver(const nsAString &aObserverKey, nsIObserver *aObserver); void CallObserver(const nsAString &aObserverKey, const nsAString &aTopic, const nsAString &aData); void RemoveObserver(const nsAString &aObserverKey); void NotifyObservers(nsISupports *aSupports, const char *aTopic, const PRUnichar *aData); void ResendLastResizeEvent(nsWindow* aDest); protected: virtual void ScheduleNativeEventCallback(); virtual ~nsAppShell(); Mutex mQueueLock; Mutex mCondLock; CondVar mQueueCond; int mNumDraws; + mozilla::AndroidGeckoEvent *mLastDrawEvent; nsTArray mEventQueue; nsInterfaceHashtable mObserversHash; - mozilla::AndroidGeckoEvent *GetNextEvent(); + mozilla::AndroidGeckoEvent *PopNextEvent(); mozilla::AndroidGeckoEvent *PeekNextEvent(); }; #endif // nsAppShell_h__