You need to set DE_RRMR (offset 0x44050) to unmask scanline waits, but this at least doesn't hang on my IVB. However I still see tearing on my config, need to verify the pipe and inclusive/exclusive setting. -- Jesse Barnes, Intel Open Source Technology Center diff --git a/src/i830_reg.h b/src/i830_reg.h index 93d03cf..bd2980a 100644 --- a/src/i830_reg.h +++ b/src/i830_reg.h @@ -52,19 +52,39 @@ /* Wait for Events */ #define MI_WAIT_FOR_EVENT (0x03<<23) +#define MI_WAIT_FOR_PIPEC_SVBLANK_SNB (1<<21) +#define MI_WAIT_FOR_PIPEB_SVBLANK_SNB (1<<11) +#define MI_WAIT_FOR_PIPEA_SVBLANK_SNB (1<<3) #define MI_WAIT_FOR_PIPEB_SVBLANK (1<<18) #define MI_WAIT_FOR_PIPEA_SVBLANK (1<<17) #define MI_WAIT_FOR_OVERLAY_FLIP (1<<16) +#define MI_WAIT_FOR_PIPEC_SCAN_LINE_WINDOW_SNB (1<<14) #define MI_WAIT_FOR_PIPEB_VBLANK (1<<7) #define MI_WAIT_FOR_PIPEB_SCAN_LINE_WINDOW (1<<5) +#define MI_WAIT_FOR_PIPEB_SCAN_LINE_WINDOW_SNB (1<<8) #define MI_WAIT_FOR_PIPEA_VBLANK (1<<3) #define MI_WAIT_FOR_PIPEA_SCAN_LINE_WINDOW (1<<1) +#define MI_WAIT_FOR_PIPEA_SCAN_LINE_WINDOW_SNB (1<<0) /* Set the scan line for MI_WAIT_FOR_PIPE?_SCAN_LINE_WINDOW */ #define MI_LOAD_SCAN_LINES_INCL (0x12<<23) #define MI_LOAD_SCAN_LINES_DISPLAY_PIPEA (0) #define MI_LOAD_SCAN_LINES_DISPLAY_PIPEB (0x1<<20) +#define MI_LOAD_SCAN_LINES_EXCL (0x13<<23) +#define MI_LOAD_SCAN_LINES_EXCL_PIPEA (0) +#define MI_LOAD_SCAN_LINES_EXCL_PIPEB (1<<19) +#define MI_LOAD_SCAN_LINES_EXCL_PIPEC (4<<19) + +#define _PIPE(pipe, a, b) ((a) + (pipe)*((b)-(a))) + +#define _DE_LOAD_SL_A 0x70068 +#define _DE_LOAD_SL_B 0x71068 +#define _DE_LOAD_SL_C 0x72068 +#define DE_LOAD_SL(pipe) _PIPE(pipe, _DE_LOAD_SL_A, _DE_LOAD_SL_B) + +#define MI_LOAD_REGISTER_IMM (0x22<<23 | 1) + /* BLT commands */ #define COLOR_BLT_CMD ((2<<29)|(0x40<<22)|(0x3)) #define COLOR_BLT_WRITE_ALPHA (1<<21) diff --git a/src/intel_dri.c b/src/intel_dri.c index f6f0c86..87633e2 100644 --- a/src/intel_dri.c +++ b/src/intel_dri.c @@ -625,6 +625,65 @@ I830DRI2CopyRegion(DrawablePtr drawable, RegionPtr pRegion, OUT_BATCH(MI_WAIT_FOR_EVENT | event); ADVANCE_BATCH(); } + } else if (pixmap_is_scanout(get_drawable_pixmap(dst)) && + intel->swapbuffers_wait && INTEL_INFO(intel)->gen >= 60) { + BoxPtr box; + BoxRec crtcbox; + int y1, y2; + int pipe = -1, event, load_scan_lines_reg; + xf86CrtcPtr crtc; + Bool full_height = FALSE; + + box = REGION_EXTENTS(unused, gc->pCompositeClip); + crtc = intel_covering_crtc(scrn, box, NULL, &crtcbox); + + /* + * Make sure the CRTC is valid and this is the real front + * buffer + */ + if (crtc != NULL && !crtc->rotatedData) { + pipe = intel_crtc_to_pipe(crtc); + + load_scan_lines_reg = DE_LOAD_SL(pipe); + + /* + * Make sure we don't wait for a scanline that will + * never occur + */ + y1 = (crtcbox.y1 <= box->y1) ? box->y1 - crtcbox.y1 : 0; + y2 = (box->y2 <= crtcbox.y2) ? + box->y2 - crtcbox.y1 : crtcbox.y2 - crtcbox.y1; + + if (y1 == 0 && y2 == (crtcbox.y2 - crtcbox.y1)) + full_height = TRUE; + + if (pipe == 0) { + event = MI_WAIT_FOR_PIPEA_SCAN_LINE_WINDOW_SNB; + if (full_height) + event = MI_WAIT_FOR_PIPEA_SVBLANK_SNB; + } else if (pipe == 1) { + event = MI_WAIT_FOR_PIPEB_SCAN_LINE_WINDOW_SNB; + if (full_height) + event = MI_WAIT_FOR_PIPEB_SVBLANK_SNB; + } else { + event = MI_WAIT_FOR_PIPEC_SCAN_LINE_WINDOW_SNB; + if (full_height) + event = MI_WAIT_FOR_PIPEC_SVBLANK_SNB; + } + + if (crtc->mode.Flags & V_INTERLACE) { + /* DSL count field lines */ + y1 /= 2; + y2 /= 2; + } + + BEGIN_BATCH_BLT(4); + OUT_BATCH(MI_LOAD_REGISTER_IMM); + OUT_BATCH(load_scan_lines_reg); + OUT_BATCH((1<<31) | (1<<30) | (y1 << 16) | (y2-1)); + OUT_BATCH(MI_WAIT_FOR_EVENT | event); + ADVANCE_BATCH(); + } } /* It's important that this copy gets submitted before the