xf86-video-intel: src/sna/sna_dri.c

Chris Wilson ickle at kemper.freedesktop.org
Wed Oct 3 05:02:57 PDT 2012


 src/sna/sna_dri.c |   27 ++++++++++++++++++++++-----
 1 file changed, 22 insertions(+), 5 deletions(-)

New commits:
commit 3e770f09dbe76287293fea0a8a1f231885aa1c1f
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Oct 3 13:00:25 2012 +0100

    sna/dri: Delay the deactivation of the pageflipping
    
    As we need to clflush the scanout buffer as we return it to the bo cache
    on SNB+, it is costly to terminate the pageflipping as soon as we drop a
    frame as mesa often fails to keep up to the vrefresh rate.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna_dri.c b/src/sna/sna_dri.c
index 69c1b42..2fc3af2 100644
--- a/src/sna/sna_dri.c
+++ b/src/sna/sna_dri.c
@@ -55,6 +55,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 #endif
 
 #define COLOR_PREFER_TILING_Y 0
+#define FLIP_OFF_DELAY 5
 
 enum frame_event_type {
 	DRI2_SWAP,
@@ -1431,8 +1432,22 @@ static void sna_dri_flip_event(struct sna *sna,
 			sna_dri_frame_event_info_free(sna, flip->draw, flip);
 			chain_flip(sna);
 		} else if (!flip->next_front.name) {
-			DBG(("%s: flip chain complete\n", __FUNCTION__));
-			sna_dri_frame_event_info_free(sna, flip->draw, flip);
+			/* Keep the pageflipping running for a couple of frames
+			 * so we keep the uncached scanouts alive.
+			 */
+			DBG(("%s: flip chain complete, off-delay=%d\n",
+			     __FUNCTION__, flip->off_delay));
+			if (flip->off_delay-- && flip->draw &&
+			    can_flip(sna, flip->draw, flip->front, flip->front) &&
+			    (flip->count = sna_page_flip(sna,
+							 get_private(flip->front)->bo,
+							 flip, flip->pipe))) {
+				assert(flip == sna_dri_window_get_chain((WindowPtr)flip->draw));
+				sna->dri.flip_pending = flip;
+			} else {
+				DBG(("%s: flip chain complete, off\n", __FUNCTION__));
+				sna_dri_frame_event_info_free(sna, flip->draw, flip);
+			}
 		} else if (flip->draw &&
 			   can_flip(sna, flip->draw, flip->front, flip->back)) {
 			sna_dri_flip_continue(sna, flip);
@@ -1445,6 +1460,7 @@ static void sna_dri_flip_event(struct sna *sna,
 				sna->dri.flip_pending = flip;
 			else
 				sna_dri_frame_event_info_free(sna, flip->draw, flip);
+			flip->off_delay = FLIP_OFF_DELAY;
 		} else {
 			DBG(("%s: no longer able to flip\n", __FUNCTION__));
 
@@ -1488,12 +1504,12 @@ static void sna_dri_flip_event(struct sna *sna,
 
 			flip->next_front.bo = get_private(flip->front)->bo;
 			flip->next_front.name = flip->front->name;
-			flip->off_delay = 5;
+			flip->off_delay = FLIP_OFF_DELAY;
 
 			sna->dri.flip_pending = flip;
 		} else if (flip->draw &&
 			   can_flip(sna, flip->draw, flip->front, flip->back) &&
-			   --flip->off_delay) {
+			   flip->off_delay--) {
 			assert(flip == sna_dri_window_get_chain((WindowPtr)flip->draw));
 			DBG(("%s: queuing no-flip [delay=%d]\n",
 			     __FUNCTION__, flip->off_delay));
@@ -1643,6 +1659,7 @@ sna_dri_schedule_flip(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
 					       CREATE_SCANOUT | CREATE_EXACT);
 			info->back->name = kgem_bo_flink(&sna->kgem,
 							 get_private(info->back)->bo);
+			info->off_delay = FLIP_OFF_DELAY;
 			sna->dri.flip_pending = info;
 
 			DRI2SwapComplete(info->client, draw, 0, 0, 0,
@@ -2080,7 +2097,7 @@ blit:
 
 		info->next_front.name = info->front->name;
 		info->next_front.bo = get_private(info->front)->bo;
-		info->off_delay = 5;
+		info->off_delay = FLIP_OFF_DELAY;
 	} else if (info->type != DRI2_ASYNC_FLIP) {
 		/* A normal vsync'ed client is finishing, wait for it
 		 * to unpin the old framebuffer before taking over.


More information about the xorg-commit mailing list