diff options
-rw-r--r-- | src/nouveau_dri2.c | 32 | ||||
-rw-r--r-- | src/nouveau_present.c | 16 | ||||
-rw-r--r-- | src/nouveau_xv.c | 94 | ||||
-rw-r--r-- | src/nv50_accel.c | 17 | ||||
-rw-r--r-- | src/nv_accel_common.c | 17 | ||||
-rw-r--r-- | src/nv_proto.h | 2 | ||||
-rw-r--r-- | src/nvc0_accel.c | 17 |
7 files changed, 138 insertions, 57 deletions
diff --git a/src/nouveau_dri2.c b/src/nouveau_dri2.c index cc16cb1..3361869 100644 --- a/src/nouveau_dri2.c +++ b/src/nouveau_dri2.c @@ -434,7 +434,7 @@ nouveau_dri2_flip_handler(void *priv, uint64_t name, uint64_t ust, uint32_t msc) static Bool dri2_page_flip(DrawablePtr draw, PixmapPtr back, void *priv, - unsigned int ref_crtc_hw_id) + xf86CrtcPtr ref_crtc) { ScrnInfoPtr scrn = xf86ScreenToScrn(draw->pScreen); xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); @@ -489,7 +489,7 @@ dri2_page_flip(DrawablePtr draw, PixmapPtr back, void *priv, /* Only the reference crtc will finally deliver its page flip * completion event. All other crtc's events will be discarded. */ - flipcarrier->dispatch_me = ((1 << i) == ref_crtc_hw_id); + flipcarrier->dispatch_me = (config->crtc[i] == ref_crtc); flipcarrier->flipdata = flipdata; ret = drmModePageFlip(pNv->dev->fd, head, next_fb, @@ -565,20 +565,19 @@ nouveau_wait_vblank(DrawablePtr draw, int type, CARD64 msc, CARD64 *pmsc, CARD64 *pust, void *data) { ScrnInfoPtr scrn = xf86ScreenToScrn(draw->pScreen); - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); NVPtr pNv = NVPTR(scrn); - int crtcs = nv_window_belongs_to_crtc(scrn, draw->x, draw->y, - draw->width, draw->height); + xf86CrtcPtr crtc; drmVBlank vbl; struct dri2_vblank *event = NULL; void *token = NULL; int ret; int head; - /* Select crtc with smallest index from bitmask of crtcs */ - crtcs = ffs(crtcs) - 1; + /* Select crtc which shows the largest part of the drawable */ + crtc = nouveau_pick_best_crtc(scrn, FALSE, + draw->x, draw->y, draw->width, draw->height); - if (crtcs < 0) { + if (!crtc) { xf86DrvMsg(scrn->scrnIndex, X_WARNING, "Wait for VBlank failed: No valid crtc for drawable.\n"); return -EINVAL; @@ -596,7 +595,7 @@ nouveau_wait_vblank(DrawablePtr draw, int type, CARD64 msc, } /* Map xf86CrtcPtr to drmWaitVBlank compatible display head index. */ - head = drmmode_head(config->crtc[crtcs]); + head = drmmode_head(crtc); if (head == 1) type |= DRM_VBLANK_SECONDARY; @@ -647,21 +646,14 @@ nouveau_dri2_finish_swap(DrawablePtr draw, unsigned int frame, RegionRec reg; int type, ret; Bool front_updated, will_exchange; + xf86CrtcPtr ref_crtc; REGION_INIT(0, ®, (&(BoxRec){ 0, 0, draw->width, draw->height }), 0); REGION_TRANSLATE(0, ®, draw->x, draw->y); /* Main crtc for this drawable shall finally deliver pageflip event. */ - unsigned int ref_crtc_hw_id = nv_window_belongs_to_crtc(scrn, draw->x, - draw->y, - draw->width, - draw->height); - - /* Choose crtc with smallest index as reference, as its - * vblank event triggered this swap. ref_crtc_hw_id is - * a bit field (crtc 0 = bit 0, crtc 1 = bit 1 ...) - */ - ref_crtc_hw_id = 1 << (ffs(ref_crtc_hw_id) - 1); + ref_crtc = nouveau_pick_best_crtc(scrn, FALSE, draw->x, draw->y, + draw->width, draw->height); /* Update frontbuffer pixmap and name: Could have changed due to * window (un)redirection as part of compositing. @@ -711,7 +703,7 @@ nouveau_dri2_finish_swap(DrawablePtr draw, unsigned int frame, if (nouveau_exa_pixmap_is_onscreen(dst_pix)) { type = DRI2_FLIP_COMPLETE; ret = dri2_page_flip(draw, src_pix, violate_oml(draw) ? - NULL : s, ref_crtc_hw_id); + NULL : s, ref_crtc); if (!ret) goto out; } diff --git a/src/nouveau_present.c b/src/nouveau_present.c index f4cdcc8..ea1686e 100644 --- a/src/nouveau_present.c +++ b/src/nouveau_present.c @@ -36,21 +36,17 @@ static RRCrtcPtr nouveau_present_crtc(WindowPtr window) { ScrnInfoPtr scrn = xf86ScreenToScrn(window->drawable.pScreen); - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); xf86CrtcPtr crtc; - unsigned mask; - int head; - mask = nv_window_belongs_to_crtc(scrn, window->drawable.x, - window->drawable.y, - window->drawable.width, - window->drawable.height); + crtc = nouveau_pick_best_crtc(scrn, FALSE, + window->drawable.x, + window->drawable.y, + window->drawable.width, + window->drawable.height); - head = ffs(mask) - 1; - if (head < 0 || head >= xf86_config->num_crtc) + if (!crtc) return NULL; - crtc = xf86_config->crtc[head]; if (crtc->rotatedData) return NULL; diff --git a/src/nouveau_xv.c b/src/nouveau_xv.c index e40d6ba..a479d38 100644 --- a/src/nouveau_xv.c +++ b/src/nouveau_xv.c @@ -196,6 +196,100 @@ static XF86ImageRec NVImages[NUM_IMAGES_ALL] = XVIMAGE_RGB }; +static void +nouveau_box_intersect(BoxPtr dest, BoxPtr a, BoxPtr b) +{ + dest->x1 = a->x1 > b->x1 ? a->x1 : b->x1; + dest->x2 = a->x2 < b->x2 ? a->x2 : b->x2; + dest->y1 = a->y1 > b->y1 ? a->y1 : b->y1; + dest->y2 = a->y2 < b->y2 ? a->y2 : b->y2; + + if (dest->x1 >= dest->x2 || dest->y1 >= dest->y2) + dest->x1 = dest->x2 = dest->y1 = dest->y2 = 0; +} + +static void +nouveau_crtc_box(xf86CrtcPtr crtc, BoxPtr crtc_box) +{ + if (crtc->enabled) { + crtc_box->x1 = crtc->x; + crtc_box->x2 = crtc->x + xf86ModeWidth(&crtc->mode, crtc->rotation); + crtc_box->y1 = crtc->y; + crtc_box->y2 = crtc->y + xf86ModeHeight(&crtc->mode, crtc->rotation); + } else + crtc_box->x1 = crtc_box->x2 = crtc_box->y1 = crtc_box->y2 = 0; +} + +static int +nouveau_box_area(BoxPtr box) +{ + return (int) (box->x2 - box->x1) * (int) (box->y2 - box->y1); +} + +xf86CrtcPtr +nouveau_pick_best_crtc(ScrnInfoPtr pScrn, Bool consider_disabled, + int x, int y, int w, int h) +{ + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + int coverage, best_coverage, c; + BoxRec box, crtc_box, cover_box; + RROutputPtr primary_output = NULL; + xf86CrtcPtr best_crtc = NULL, primary_crtc = NULL; + + if (!pScrn->vtSema) + return NULL; + + box.x1 = x; + box.x2 = x + w; + box.y1 = y; + box.y2 = y + h; + best_coverage = 0; + + /* Prefer the CRTC of the primary output */ +#ifdef HAS_DIXREGISTERPRIVATEKEY + if (dixPrivateKeyRegistered(rrPrivKey)) +#endif + { + primary_output = RRFirstOutput(pScrn->pScreen); + } + if (primary_output && primary_output->crtc) + primary_crtc = primary_output->crtc->devPrivate; + + /* first consider only enabled CRTCs */ + for (c = 0; c < xf86_config->num_crtc; c++) { + xf86CrtcPtr crtc = xf86_config->crtc[c]; + + if (!crtc->enabled) + continue; + + nouveau_crtc_box(crtc, &crtc_box); + nouveau_box_intersect(&cover_box, &crtc_box, &box); + coverage = nouveau_box_area(&cover_box); + if (coverage > best_coverage || + (coverage == best_coverage && crtc == primary_crtc)) { + best_crtc = crtc; + best_coverage = coverage; + } + } + if (best_crtc || !consider_disabled) + return best_crtc; + + /* if we found nothing, repeat the search including disabled CRTCs */ + for (c = 0; c < xf86_config->num_crtc; c++) { + xf86CrtcPtr crtc = xf86_config->crtc[c]; + + nouveau_crtc_box(crtc, &crtc_box); + nouveau_box_intersect(&cover_box, &crtc_box, &box); + coverage = nouveau_box_area(&cover_box); + if (coverage > best_coverage || + (coverage == best_coverage && crtc == primary_crtc)) { + best_crtc = crtc; + best_coverage = coverage; + } + } + return best_crtc; +} + unsigned int nv_window_belongs_to_crtc(ScrnInfoPtr pScrn, int x, int y, int w, int h) { diff --git a/src/nv50_accel.c b/src/nv50_accel.c index 3d489d0..b27f67a 100644 --- a/src/nv50_accel.c +++ b/src/nv50_accel.c @@ -31,25 +31,24 @@ void NV50SyncToVBlank(PixmapPtr ppix, BoxPtr box) { ScrnInfoPtr pScrn = xf86ScreenToScrn(ppix->drawable.pScreen); - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); NVPtr pNv = NVPTR(pScrn); struct nouveau_pushbuf *push = pNv->pushbuf; - int crtcs; + int head; + xf86CrtcPtr crtc; if (!nouveau_exa_pixmap_is_onscreen(ppix)) return; - crtcs = nv_window_belongs_to_crtc(pScrn, box->x1, box->y1, - box->x2 - box->x1, - box->y2 - box->y1); - if (!crtcs) + crtc = nouveau_pick_best_crtc(pScrn, FALSE, box->x1, box->y1, + box->x2 - box->x1, + box->y2 - box->y1); + if (!crtc) return; if (!PUSH_SPACE(push, 10)) return; - crtcs = ffs(crtcs) - 1; - crtcs = drmmode_head(config->crtc[crtcs]); + head = drmmode_head(crtc); BEGIN_NV04(push, SUBC_NVSW(0x0060), 2); PUSH_DATA (push, pNv->vblank_sem->handle); @@ -58,7 +57,7 @@ NV50SyncToVBlank(PixmapPtr ppix, BoxPtr box) PUSH_DATA (push, 0x22222222); BEGIN_NV04(push, SUBC_NVSW(0x0404), 2); PUSH_DATA (push, 0x11111111); - PUSH_DATA (push, crtcs); + PUSH_DATA (push, head); BEGIN_NV04(push, SUBC_NVSW(0x0068), 1); PUSH_DATA (push, 0x11111111); } diff --git a/src/nv_accel_common.c b/src/nv_accel_common.c index bd9dc8a..4484c1c 100644 --- a/src/nv_accel_common.c +++ b/src/nv_accel_common.c @@ -133,30 +133,29 @@ void NV11SyncToVBlank(PixmapPtr ppix, BoxPtr box) { ScrnInfoPtr pScrn = xf86ScreenToScrn(ppix->drawable.pScreen); - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); NVPtr pNv = NVPTR(pScrn); struct nouveau_pushbuf *push = pNv->pushbuf; - int crtcs; + int head; + xf86CrtcPtr crtc; if (!nouveau_exa_pixmap_is_onscreen(ppix)) return; - crtcs = nv_window_belongs_to_crtc(pScrn, box->x1, box->y1, - box->x2 - box->x1, - box->y2 - box->y1); - if (!crtcs) + crtc = nouveau_pick_best_crtc(pScrn, FALSE, box->x1, box->y1, + box->x2 - box->x1, + box->y2 - box->y1); + if (!crtc) return; if (!PUSH_SPACE(push, 8)) return; - crtcs = ffs(crtcs) - 1; - crtcs = drmmode_head(config->crtc[crtcs]); + head = drmmode_head(crtc); BEGIN_NV04(push, SUBC_BLIT(0x0000012C), 1); PUSH_DATA (push, 0); BEGIN_NV04(push, SUBC_BLIT(0x00000134), 1); - PUSH_DATA (push, crtcs); + PUSH_DATA (push, head); BEGIN_NV04(push, SUBC_BLIT(0x00000100), 1); PUSH_DATA (push, 0); BEGIN_NV04(push, SUBC_BLIT(0x00000130), 1); diff --git a/src/nv_proto.h b/src/nv_proto.h index 27354e0..cc4fd09 100644 --- a/src/nv_proto.h +++ b/src/nv_proto.h @@ -43,6 +43,8 @@ void NVTakedownVideo(ScrnInfoPtr); void NVSetPortDefaults (ScrnInfoPtr pScrn, NVPortPrivPtr pPriv); void NVXVComputeBicubicFilter(struct nouveau_bo *, unsigned, unsigned); unsigned int nv_window_belongs_to_crtc(ScrnInfoPtr, int, int, int, int); +xf86CrtcPtr nouveau_pick_best_crtc(ScrnInfoPtr pScrn, Bool consider_disabled, + int x, int y, int w, int h); /* in nouveau_exa.c */ Bool nouveau_exa_init(ScreenPtr pScreen); diff --git a/src/nvc0_accel.c b/src/nvc0_accel.c index 375ccc8..c04e270 100644 --- a/src/nvc0_accel.c +++ b/src/nvc0_accel.c @@ -63,25 +63,24 @@ void NVC0SyncToVBlank(PixmapPtr ppix, BoxPtr box) { ScrnInfoPtr pScrn = xf86ScreenToScrn(ppix->drawable.pScreen); - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); NVPtr pNv = NVPTR(pScrn); struct nouveau_pushbuf *push = pNv->pushbuf; - int crtcs; + int head; + xf86CrtcPtr crtc; if (!pNv->NvSW || !nouveau_exa_pixmap_is_onscreen(ppix)) return; - crtcs = nv_window_belongs_to_crtc(pScrn, box->x1, box->y1, - box->x2 - box->x1, - box->y2 - box->y1); - if (!crtcs) + crtc = nouveau_pick_best_crtc(pScrn, FALSE, box->x1, box->y1, + box->x2 - box->x1, + box->y2 - box->y1); + if (!crtc) return; if (!PUSH_SPACE(push, 32)) return; - crtcs = ffs(crtcs) - 1; - crtcs = drmmode_head(config->crtc[crtcs]); + head = drmmode_head(crtc); BEGIN_NVC0(push, NV01_SUBC(NVSW, OBJECT), 1); PUSH_DATA (push, pNv->NvSW->handle); @@ -94,7 +93,7 @@ NVC0SyncToVBlank(PixmapPtr ppix, BoxPtr box) PUSH_DATA (push, (pNv->scratch->offset + SEMA_OFFSET) >> 32); PUSH_DATA (push, (pNv->scratch->offset + SEMA_OFFSET)); PUSH_DATA (push, 0x11111111); - PUSH_DATA (push, crtcs); + PUSH_DATA (push, head); BEGIN_NVC0(push, NV84_SUBC(NVSW, SEMAPHORE_ADDRESS_HIGH), 4); PUSH_DATA (push, (pNv->scratch->offset + SEMA_OFFSET) >> 32); PUSH_DATA (push, (pNv->scratch->offset + SEMA_OFFSET)); |