Maarten Lankhorst
2012-Jul-27 12:38 UTC
[Nouveau] [PATCH] nvc0: Add and enable vblank support
Based on the original patch by Christoph Bumiller, but since
it depends on kernel support patched I cannot push it yet.
The changes are that I enable vblank by default, and offset
takes OFFSET_HIGH/LOW instead of something relative to notifier_bo.
Signed-off-by: Maarten Lankhorst <maarten.lankhorst at canonical.com>
---
diff --git a/man/nouveau.man b/man/nouveau.man
index 7c72907..8765569 100644
--- a/man/nouveau.man
+++ b/man/nouveau.man
@@ -79,7 +79,7 @@ Enable or disable wfb, only affects nv50+. Useful for some
legacy configurations
.BI "Option \*qGLXVBlank\*q \*q" boolean \*q
Synchronize GLX clients to VBlank. Useful where tearing is a problem,
harmful if the GPU isn't fast enough to keep up with the monitor
-refresh rate. Default: off.
+refresh rate. Default: on.
.TP
.BI "Option \*qZaphodHeads\*q \*q" string \*q
Specify the randr output(s) to use with zaphod mode for a particular driver
diff --git a/src/nouveau_dri2.c b/src/nouveau_dri2.c
index 0b3cc38..62333b1 100644
--- a/src/nouveau_dri2.c
+++ b/src/nouveau_dri2.c
@@ -316,6 +316,9 @@ nouveau_dri2_finish_swap(DrawablePtr draw, unsigned int
frame,
NOUVEAU_BO_VRAM | NOUVEAU_BO_RD
}, 1);
+ if (pNv->Architecture >= NV_ARCH_C0)
+ NVC0SyncToVBlank(dst_pix, REGION_EXTENTS(0, ®));
+ else
if (pNv->Architecture >= NV_ARCH_50)
NV50SyncToVBlank(dst_pix, REGION_EXTENTS(0, ®));
else
diff --git a/src/nv_dma.c b/src/nv_dma.c
index d2a6d00..47c7e12 100644
--- a/src/nv_dma.c
+++ b/src/nv_dma.c
@@ -63,6 +63,18 @@ NVInitDma(ScrnInfoPtr pScrn)
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"Opened GPU channel %d\n", fifo->channel);
+ if (pNv->Architecture >= NV_ARCH_C0) {
+ struct nvc0_fifo *data = (struct nvc0_fifo *)fifo;
+ ret = nouveau_bo_wrap(pNv->dev, data->notify,
+ &pNv->notifier_bo);
+ if (ret) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Failed to obtain notifier bo: %d\n", ret);
+ NVTakedownDma(pScrn);
+ return FALSE;
+ }
+ }
+
ret = nouveau_pushbuf_new(pNv->client, pNv->channel, 4, 32 * 1024,
true, &pNv->pushbuf);
if (ret) {
diff --git a/src/nv_driver.c b/src/nv_driver.c
index beef789..dd6f005 100644
--- a/src/nv_driver.c
+++ b/src/nv_driver.c
@@ -815,6 +815,7 @@ NVPreInit(ScrnInfoPtr pScrn, int flags)
if (!pNv->NoAccel && pNv->dev->chipset >= 0x11) {
from = X_DEFAULT;
+ pNv->glx_vblank = TRUE;
if (xf86GetOptValBool(pNv->Options, OPTION_GLX_VBLANK,
&pNv->glx_vblank))
from = X_CONFIG;
diff --git a/src/nv_proto.h b/src/nv_proto.h
index b546ebd..bcf927d 100644
--- a/src/nv_proto.h
+++ b/src/nv_proto.h
@@ -149,6 +149,7 @@ Bool NVAccelInit2D_NV50(ScrnInfoPtr pScrn);
Bool NVAccelInitNV50TCL(ScrnInfoPtr pScrn);
/* in nvc0_accel.c */
+void NVC0SyncToVBlank(PixmapPtr ppix, BoxPtr box);
Bool NVAccelInitM2MF_NVC0(ScrnInfoPtr pScrn);
Bool NVAccelInitCopy_NVC0(ScrnInfoPtr pScrn);
Bool NVAccelInitP2MF_NVE0(ScrnInfoPtr pScrn);
diff --git a/src/nv_type.h b/src/nv_type.h
index e1ea494..272e34f 100644
--- a/src/nv_type.h
+++ b/src/nv_type.h
@@ -102,6 +102,7 @@ typedef struct _NVRec {
struct nouveau_object *Nv2D;
struct nouveau_object *Nv3D;
struct nouveau_object *NvSW;
+ struct nouveau_bo *notifier_bo;
struct nouveau_bo *scratch;
Bool ce_enabled;
diff --git a/src/nvc0_accel.c b/src/nvc0_accel.c
index c5da0cd..4cae0d2 100644
--- a/src/nvc0_accel.c
+++ b/src/nvc0_accel.c
@@ -25,6 +25,36 @@
#include "nvc0_shader.h"
#include "nve0_shader.h"
+void
+NVC0SyncToVBlank(PixmapPtr ppix, BoxPtr box)
+{
+ ScrnInfoPtr pScrn = xf86Screens[ppix->drawable.pScreen->myNum];
+ NVPtr pNv = NVPTR(pScrn);
+ struct nouveau_pushbuf *push = pNv->pushbuf;
+ int crtcs;
+
+ 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)
+ return;
+
+ BEGIN_NVC0(push, SUBC_NVSW(NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH), 4);
+ PUSH_DATA (push, pNv->notifier_bo->offset >> 32);
+ PUSH_DATA (push, pNv->notifier_bo->offset);
+ PUSH_DATA (push, 0x22222222);
+ PUSH_DATA (push, NV84_SUBCHAN_SEMAPHORE_TRIGGER_WRITE_LONG);
+ BEGIN_NVC0(push, SUBC_NVSW(0x0208), 2);
+ PUSH_DATA (push, 0x11111111);
+ PUSH_DATA (push, ffs(crtcs) - 1);
+ BEGIN_NVC0(push, SUBC_NVSW(NV84_SUBCHAN_SEMAPHORE_SEQUENCE), 2);
+ PUSH_DATA (push, 0x11111111);
+ PUSH_DATA (push, NV84_SUBCHAN_SEMAPHORE_TRIGGER_ACQUIRE_EQUAL);
+}
+
Bool
NVAccelInitM2MF_NVC0(ScrnInfoPtr pScrn)
{
@@ -153,12 +183,27 @@ NVAccelInit3D_NVC0(ScrnInfoPtr pScrn)
if (ret)
return FALSE;
+ ret = nouveau_object_new(pNv->channel, 0x906e, 0x906e,
+ NULL, 0, &pNv->NvSW);
+
if (nouveau_pushbuf_space(push, 512, 0, 0) ||
nouveau_pushbuf_refn (push, &(struct nouveau_pushbuf_refn) {
pNv->scratch, NOUVEAU_BO_VRAM |
NOUVEAU_BO_WR }, 1))
return FALSE;
+ if (!ret) {
+ BEGIN_NVC0(push, NV01_SUBC(NVSW, OBJECT), 1);
+ PUSH_DATA (push, pNv->NvSW->handle);
+ BEGIN_NVC0(push, SUBC_NVSW(0x0200), 2); /* VBLSEM_OFFSET */
+ PUSH_DATA (push, pNv->notifier_bo->offset >> 32);
+ PUSH_DATA (push, pNv->notifier_bo->offset);
+ } else if (pNv->glx_vblank) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "No kernel support for GLX sync to VBlank.\n");
+ pNv->glx_vblank = false;
+ }
+
BEGIN_NVC0(push, NV01_SUBC(3D, OBJECT), 1);
PUSH_DATA (push, pNv->Nv3D->handle);
BEGIN_NVC0(push, NVC0_3D(COND_MODE), 1);
diff --git a/src/nvc0_xv.c b/src/nvc0_xv.c
index 3b6d01f..86b7948 100644
--- a/src/nvc0_xv.c
+++ b/src/nvc0_xv.c
@@ -221,9 +221,8 @@ nvc0_xv_image_put(ScrnInfoPtr pScrn,
PUSH_DATAf(push, 1.0 / width);
PUSH_DATAf(push, 1.0 / height);
- if (0 && pPriv->SyncToVBlank) {
- NV50SyncToVBlank(ppix, dstBox);
- }
+ if (pPriv->SyncToVBlank)
+ NVC0SyncToVBlank(ppix, dstBox);
/* These are fixed point values in the 16.16 format. */
X1 = (float)(x1>>16)+(float)(x1&0xFFFF)/(float)0x10000;
On Fri, Jul 27, 2012 at 10:38 PM, Maarten Lankhorst <maarten.lankhorst at canonical.com> wrote:> Based on the original patch by Christoph Bumiller, but since > it depends on kernel support patched I cannot push it yet.Hey Maarten, I've pushed support for sync-to-vblank on fermi and up (tested on NVC0, NVD9 and NVE7) to the DRM (in the rework code) and the DDX. There's a few differences to your code, mostly for NVC0 where we use PFIFO SWMTHD rather than PGRAPH ILLEGAL_CLASS for the software traps. Also, I tracked down (on NVD9) an issue where we get far more vblank interrupts than expected, turns out vblank is a sub-status of what you were using. Let me know if there's any issues. Ben.> > The changes are that I enable vblank by default, and offset > takes OFFSET_HIGH/LOW instead of something relative to notifier_bo. > > Signed-off-by: Maarten Lankhorst <maarten.lankhorst at canonical.com> > > --- > diff --git a/man/nouveau.man b/man/nouveau.man > index 7c72907..8765569 100644 > --- a/man/nouveau.man > +++ b/man/nouveau.man > @@ -79,7 +79,7 @@ Enable or disable wfb, only affects nv50+. Useful for some legacy configurations > .BI "Option \*qGLXVBlank\*q \*q" boolean \*q > Synchronize GLX clients to VBlank. Useful where tearing is a problem, > harmful if the GPU isn't fast enough to keep up with the monitor > -refresh rate. Default: off. > +refresh rate. Default: on. > .TP > .BI "Option \*qZaphodHeads\*q \*q" string \*q > Specify the randr output(s) to use with zaphod mode for a particular driver > diff --git a/src/nouveau_dri2.c b/src/nouveau_dri2.c > index 0b3cc38..62333b1 100644 > --- a/src/nouveau_dri2.c > +++ b/src/nouveau_dri2.c > @@ -316,6 +316,9 @@ nouveau_dri2_finish_swap(DrawablePtr draw, unsigned int frame, > NOUVEAU_BO_VRAM | NOUVEAU_BO_RD > }, 1); > > + if (pNv->Architecture >= NV_ARCH_C0) > + NVC0SyncToVBlank(dst_pix, REGION_EXTENTS(0, ®)); > + else > if (pNv->Architecture >= NV_ARCH_50) > NV50SyncToVBlank(dst_pix, REGION_EXTENTS(0, ®)); > else > diff --git a/src/nv_dma.c b/src/nv_dma.c > index d2a6d00..47c7e12 100644 > --- a/src/nv_dma.c > +++ b/src/nv_dma.c > @@ -63,6 +63,18 @@ NVInitDma(ScrnInfoPtr pScrn) > xf86DrvMsg(pScrn->scrnIndex, X_INFO, > "Opened GPU channel %d\n", fifo->channel); > > + if (pNv->Architecture >= NV_ARCH_C0) { > + struct nvc0_fifo *data = (struct nvc0_fifo *)fifo; > + ret = nouveau_bo_wrap(pNv->dev, data->notify, > + &pNv->notifier_bo); > + if (ret) { > + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, > + "Failed to obtain notifier bo: %d\n", ret); > + NVTakedownDma(pScrn); > + return FALSE; > + } > + } > + > ret = nouveau_pushbuf_new(pNv->client, pNv->channel, 4, 32 * 1024, > true, &pNv->pushbuf); > if (ret) { > diff --git a/src/nv_driver.c b/src/nv_driver.c > index beef789..dd6f005 100644 > --- a/src/nv_driver.c > +++ b/src/nv_driver.c > @@ -815,6 +815,7 @@ NVPreInit(ScrnInfoPtr pScrn, int flags) > > if (!pNv->NoAccel && pNv->dev->chipset >= 0x11) { > from = X_DEFAULT; > + pNv->glx_vblank = TRUE; > if (xf86GetOptValBool(pNv->Options, OPTION_GLX_VBLANK, > &pNv->glx_vblank)) > from = X_CONFIG; > diff --git a/src/nv_proto.h b/src/nv_proto.h > index b546ebd..bcf927d 100644 > --- a/src/nv_proto.h > +++ b/src/nv_proto.h > @@ -149,6 +149,7 @@ Bool NVAccelInit2D_NV50(ScrnInfoPtr pScrn); > Bool NVAccelInitNV50TCL(ScrnInfoPtr pScrn); > > /* in nvc0_accel.c */ > +void NVC0SyncToVBlank(PixmapPtr ppix, BoxPtr box); > Bool NVAccelInitM2MF_NVC0(ScrnInfoPtr pScrn); > Bool NVAccelInitCopy_NVC0(ScrnInfoPtr pScrn); > Bool NVAccelInitP2MF_NVE0(ScrnInfoPtr pScrn); > diff --git a/src/nv_type.h b/src/nv_type.h > index e1ea494..272e34f 100644 > --- a/src/nv_type.h > +++ b/src/nv_type.h > @@ -102,6 +102,7 @@ typedef struct _NVRec { > struct nouveau_object *Nv2D; > struct nouveau_object *Nv3D; > struct nouveau_object *NvSW; > + struct nouveau_bo *notifier_bo; > struct nouveau_bo *scratch; > > Bool ce_enabled; > diff --git a/src/nvc0_accel.c b/src/nvc0_accel.c > index c5da0cd..4cae0d2 100644 > --- a/src/nvc0_accel.c > +++ b/src/nvc0_accel.c > @@ -25,6 +25,36 @@ > #include "nvc0_shader.h" > #include "nve0_shader.h" > > +void > +NVC0SyncToVBlank(PixmapPtr ppix, BoxPtr box) > +{ > + ScrnInfoPtr pScrn = xf86Screens[ppix->drawable.pScreen->myNum]; > + NVPtr pNv = NVPTR(pScrn); > + struct nouveau_pushbuf *push = pNv->pushbuf; > + int crtcs; > + > + 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) > + return; > + > + BEGIN_NVC0(push, SUBC_NVSW(NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH), 4); > + PUSH_DATA (push, pNv->notifier_bo->offset >> 32); > + PUSH_DATA (push, pNv->notifier_bo->offset); > + PUSH_DATA (push, 0x22222222); > + PUSH_DATA (push, NV84_SUBCHAN_SEMAPHORE_TRIGGER_WRITE_LONG); > + BEGIN_NVC0(push, SUBC_NVSW(0x0208), 2); > + PUSH_DATA (push, 0x11111111); > + PUSH_DATA (push, ffs(crtcs) - 1); > + BEGIN_NVC0(push, SUBC_NVSW(NV84_SUBCHAN_SEMAPHORE_SEQUENCE), 2); > + PUSH_DATA (push, 0x11111111); > + PUSH_DATA (push, NV84_SUBCHAN_SEMAPHORE_TRIGGER_ACQUIRE_EQUAL); > +} > + > Bool > NVAccelInitM2MF_NVC0(ScrnInfoPtr pScrn) > { > @@ -153,12 +183,27 @@ NVAccelInit3D_NVC0(ScrnInfoPtr pScrn) > if (ret) > return FALSE; > > + ret = nouveau_object_new(pNv->channel, 0x906e, 0x906e, > + NULL, 0, &pNv->NvSW); > + > if (nouveau_pushbuf_space(push, 512, 0, 0) || > nouveau_pushbuf_refn (push, &(struct nouveau_pushbuf_refn) { > pNv->scratch, NOUVEAU_BO_VRAM | > NOUVEAU_BO_WR }, 1)) > return FALSE; > > + if (!ret) { > + BEGIN_NVC0(push, NV01_SUBC(NVSW, OBJECT), 1); > + PUSH_DATA (push, pNv->NvSW->handle); > + BEGIN_NVC0(push, SUBC_NVSW(0x0200), 2); /* VBLSEM_OFFSET */ > + PUSH_DATA (push, pNv->notifier_bo->offset >> 32); > + PUSH_DATA (push, pNv->notifier_bo->offset); > + } else if (pNv->glx_vblank) { > + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, > + "No kernel support for GLX sync to VBlank.\n"); > + pNv->glx_vblank = false; > + } > + > BEGIN_NVC0(push, NV01_SUBC(3D, OBJECT), 1); > PUSH_DATA (push, pNv->Nv3D->handle); > BEGIN_NVC0(push, NVC0_3D(COND_MODE), 1); > diff --git a/src/nvc0_xv.c b/src/nvc0_xv.c > index 3b6d01f..86b7948 100644 > --- a/src/nvc0_xv.c > +++ b/src/nvc0_xv.c > @@ -221,9 +221,8 @@ nvc0_xv_image_put(ScrnInfoPtr pScrn, > PUSH_DATAf(push, 1.0 / width); > PUSH_DATAf(push, 1.0 / height); > > - if (0 && pPriv->SyncToVBlank) { > - NV50SyncToVBlank(ppix, dstBox); > - } > + if (pPriv->SyncToVBlank) > + NVC0SyncToVBlank(ppix, dstBox); > > /* These are fixed point values in the 16.16 format. */ > X1 = (float)(x1>>16)+(float)(x1&0xFFFF)/(float)0x10000; > > _______________________________________________ > Nouveau mailing list > Nouveau at lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/nouveau
Maybe Matching Threads
- [PATCH] nv50: fix crash in NV50SyncToVBlank
- [PATCH 4/5] nvc0: refactor TIC uploads to allow different specifies per generation
- [PATCH ddx] Add support for VRAM-less devices to the ddx
- [PATCH v2 5/7] nvc0: refactor TIC uploads to allow different specifics per generation
- [PATCH v2 0/7] Add Maxwell support