reduce the number of repaintings by repaiting (rect) union of all invalidated areas instead of iterating over every Refresh() request including duplicate ones
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@41425 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
		@@ -15,7 +15,6 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#ifndef WX_PRECOMP
 | 
					#ifndef WX_PRECOMP
 | 
				
			||||||
    #include "wx/app.h"
 | 
					    #include "wx/app.h"
 | 
				
			||||||
    #include "wx/dynarray.h"
 | 
					 | 
				
			||||||
#endif // WX_PRECOMP
 | 
					#endif // WX_PRECOMP
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "wx/hashmap.h"
 | 
					#include "wx/hashmap.h"
 | 
				
			||||||
@@ -39,16 +38,6 @@ static wxDfbWindowsMap gs_dfbWindowsMap;
 | 
				
			|||||||
// helpers
 | 
					// helpers
 | 
				
			||||||
// ============================================================================
 | 
					// ============================================================================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct wxDfbPaintRequest
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    wxDfbPaintRequest(const wxRect& rect) : m_rect(rect) {}
 | 
					 | 
				
			||||||
    wxDfbPaintRequest(const wxDfbPaintRequest& r) : m_rect(r.m_rect) {}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    wxRect m_rect;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
WX_DEFINE_ARRAY_PTR(wxDfbPaintRequest*, wxDfbQueuedPaintRequestsList);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Queue of paint requests
 | 
					// Queue of paint requests
 | 
				
			||||||
class wxDfbQueuedPaintRequests
 | 
					class wxDfbQueuedPaintRequests
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@@ -57,19 +46,35 @@ public:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    // Adds paint request to the queue
 | 
					    // Adds paint request to the queue
 | 
				
			||||||
    void Add(const wxRect& rect)
 | 
					    void Add(const wxRect& rect)
 | 
				
			||||||
        { m_queue.push_back(new wxDfbPaintRequest(rect)); }
 | 
					    {
 | 
				
			||||||
 | 
					        // We use a simple implementation here for now: all refresh requests
 | 
				
			||||||
 | 
					        // are merged together into single rectangle that is superset of
 | 
				
			||||||
 | 
					        // all the requested rectangles. This wastes some blitting and painting
 | 
				
			||||||
 | 
					        // time, but OTOH, EVT_PAINT handler is called only once per window.
 | 
				
			||||||
 | 
					        m_invalidated.Union(rect);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Is the queue empty?
 | 
					    // Is the queue empty?
 | 
				
			||||||
    bool IsEmpty() const { return m_queue.empty(); }
 | 
					    bool IsEmpty() const { return m_invalidated.IsEmpty(); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Empties the queue
 | 
					    // Empties the queue
 | 
				
			||||||
    void Clear() { WX_CLEAR_ARRAY(m_queue); }
 | 
					    void Clear() { m_invalidated = wxRect(); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Gets requests in the queue
 | 
					    // Gets the next request in the queue, returns true if there was one,
 | 
				
			||||||
    const wxDfbQueuedPaintRequestsList& GetRequests() const { return m_queue; }
 | 
					    // false if the queue was empty
 | 
				
			||||||
 | 
					    bool GetNext(wxRect& rect)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if ( m_invalidated.IsEmpty() )
 | 
				
			||||||
 | 
					            return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        rect = m_invalidated;
 | 
				
			||||||
 | 
					        Clear(); // there's only one item in the queue
 | 
				
			||||||
 | 
					        return true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
    wxDfbQueuedPaintRequestsList m_queue;
 | 
					    // currently invalidated region
 | 
				
			||||||
 | 
					    wxRect m_invalidated;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ============================================================================
 | 
					// ============================================================================
 | 
				
			||||||
@@ -384,8 +389,6 @@ void wxTopLevelWindowDFB::HandleQueuedPaintRequests()
 | 
				
			|||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const wxDfbQueuedPaintRequestsList& requests = m_toPaint->GetRequests();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // process queued paint requests:
 | 
					    // process queued paint requests:
 | 
				
			||||||
    wxRect winRect(wxPoint(0, 0), GetSize());
 | 
					    wxRect winRect(wxPoint(0, 0), GetSize());
 | 
				
			||||||
    wxRect paintedRect;
 | 
					    wxRect paintedRect;
 | 
				
			||||||
@@ -395,15 +398,17 @@ void wxTopLevelWindowDFB::HandleQueuedPaintRequests()
 | 
				
			|||||||
    // blit the entire back buffer to front soon
 | 
					    // blit the entire back buffer to front soon
 | 
				
			||||||
    m_isPainting = true;
 | 
					    m_isPainting = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    size_t cnt = requests.size();
 | 
					#ifdef __WXDEBUG__
 | 
				
			||||||
    wxLogTrace(TRACE_PAINT, _T("%p ('%s'): processing %i paint requests"),
 | 
					    int requestsCount = 0;
 | 
				
			||||||
               this, GetName().c_str(), cnt);
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for ( size_t i = 0; i < cnt; ++i )
 | 
					    wxRect request;
 | 
				
			||||||
 | 
					    while ( m_toPaint->GetNext(request) )
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        const wxDfbPaintRequest& request = *requests[i];
 | 
					#ifdef __WXDEBUG__
 | 
				
			||||||
 | 
					        requestsCount++;
 | 
				
			||||||
        wxRect clipped(request.m_rect);
 | 
					#endif
 | 
				
			||||||
 | 
					        wxRect clipped(request);
 | 
				
			||||||
        clipped.Intersect(winRect);
 | 
					        clipped.Intersect(winRect);
 | 
				
			||||||
        if ( clipped.IsEmpty() )
 | 
					        if ( clipped.IsEmpty() )
 | 
				
			||||||
            continue; // nothing to refresh
 | 
					            continue; // nothing to refresh
 | 
				
			||||||
@@ -448,8 +453,9 @@ void wxTopLevelWindowDFB::HandleQueuedPaintRequests()
 | 
				
			|||||||
    GetDfbSurface()->FlipToFront(rptr);
 | 
					    GetDfbSurface()->FlipToFront(rptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    wxLogTrace(TRACE_PAINT,
 | 
					    wxLogTrace(TRACE_PAINT,
 | 
				
			||||||
               _T("%p ('%s'): flipped surface: [%i,%i,%i,%i]"),
 | 
					               _T("%p ('%s'): processed %i paint requests, flipped surface: [%i,%i,%i,%i]"),
 | 
				
			||||||
               this, GetName().c_str(),
 | 
					               this, GetName().c_str(),
 | 
				
			||||||
 | 
					               requestsCount,
 | 
				
			||||||
               paintedRect.x, paintedRect.y,
 | 
					               paintedRect.x, paintedRect.y,
 | 
				
			||||||
               paintedRect.GetRight(), paintedRect.GetBottom());
 | 
					               paintedRect.GetRight(), paintedRect.GetBottom());
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user