configure.ac | 2 man/nouveau.man | 18 +++ src/drmmode_display.c | 265 +++++++++++++++++++++++++++++++++----------- src/nouveau_class.h | 2 src/nouveau_dri2.c | 298 +++++++++++++++++++++++++++++++++++++++++++++++++- src/nouveau_exa.c | 52 +------- src/nouveau_local.h | 11 + src/nouveau_wfb.c | 2 src/nouveau_xv.c | 17 -- src/nv04_exa.c | 35 +++++ src/nv04_xv_blit.c | 11 - src/nv30_xv_tex.c | 19 --- src/nv40_xv_tex.c | 19 --- src/nv50_accel.c | 33 +++++ src/nv50_xv.c | 32 ----- src/nv_accel_common.c | 95 +++++++++++++++ src/nv_const.h | 8 + src/nv_dma.c | 3 src/nv_driver.c | 107 +++++++++++------ src/nv_include.h | 2 src/nv_proto.h | 14 +- src/nv_type.h | 8 + 22 files changed, 806 insertions(+), 247 deletions(-)
New commits: commit 8bb8231236a6b877895663aeaa9cef731d67fe68 Author: Ben Skeggs <bske...@redhat.com> Date: Tue Nov 30 15:27:36 2010 +1000 dri2: fix certain clients blocking forever when sync-to-vblank unavailable Signed-off-by: Ben Skeggs <bske...@redhat.com> diff --git a/src/nouveau_dri2.c b/src/nouveau_dri2.c index 969c6f3..2dd6da4 100644 --- a/src/nouveau_dri2.c +++ b/src/nouveau_dri2.c @@ -322,8 +322,10 @@ nouveau_dri2_schedule_wait(ClientPtr client, DrawablePtr draw, CARD64 current_msc; int ret; - if (!can_sync_to_vblank(draw)) + if (!can_sync_to_vblank(draw)) { + DRI2WaitMSCComplete(client, draw, target_msc, 0, 0); return TRUE; + } /* Initialize a vblank structure */ s = malloc(sizeof(*s)); commit f29afe65b67c9b89ceba421d9b3aee590f7ded20 Author: Ben Skeggs <bske...@redhat.com> Date: Mon Nov 29 09:23:35 2010 +1000 dri2: don't return failure from get_msc if sync-to-vblank isn't available Signed-off-by: Ben Skeggs <bske...@redhat.com> diff --git a/src/nouveau_dri2.c b/src/nouveau_dri2.c index 48e134e..969c6f3 100644 --- a/src/nouveau_dri2.c +++ b/src/nouveau_dri2.c @@ -363,8 +363,11 @@ nouveau_dri2_get_msc(DrawablePtr draw, CARD64 *ust, CARD64 *msc) { int ret; - if (!can_sync_to_vblank(draw)) - return FALSE; + if (!can_sync_to_vblank(draw)) { + *ust = 0; + *msc = 0; + return TRUE; + } /* Get current sequence */ ret = nouveau_wait_vblank(draw, DRM_VBLANK_RELATIVE, 0, msc, ust, NULL); commit 4b1d26578116f4d1745dd92a7c99413972a2bedf Author: Francisco Jerez <curroje...@riseup.net> Date: Thu Nov 25 21:33:46 2010 +0100 dri2: Don't return failure from schedule_wait if sync-to-vblank is unavailable. Reported-by: Ben Skeggs <bske...@redhat.com> Signed-off-by: Francisco Jerez <curroje...@riseup.net> diff --git a/src/nouveau_dri2.c b/src/nouveau_dri2.c index 204ab32..48e134e 100644 --- a/src/nouveau_dri2.c +++ b/src/nouveau_dri2.c @@ -323,7 +323,7 @@ nouveau_dri2_schedule_wait(ClientPtr client, DrawablePtr draw, int ret; if (!can_sync_to_vblank(draw)) - return FALSE; + return TRUE; /* Initialize a vblank structure */ s = malloc(sizeof(*s)); commit 1143e7a97dce1b741376e178b73b8b766e03849a Author: Jesse Adkins <jesserayadk...@gmail.com> Date: Tue Oct 26 16:05:32 2010 -0700 Purge cvs tags. Signed-off-by: Jesse Adkins <jesserayadk...@gmail.com> Signed-off-by: Francisco Jerez <curroje...@riseup.net> diff --git a/src/nv_const.h b/src/nv_const.h index f80d125..01ffc2c 100644 --- a/src/nv_const.h +++ b/src/nv_const.h @@ -1,5 +1,3 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/nv_const.h,v 1.6 2001/12/07 00:09:55 mvojkovi Exp $ */ - #ifndef __NV_CONST_H__ #define __NV_CONST_H__ diff --git a/src/nv_include.h b/src/nv_include.h index ce89596..48f0b21 100644 --- a/src/nv_include.h +++ b/src/nv_include.h @@ -1,5 +1,3 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/nv_include.h,v 1.9 2000/10/06 12:31:03 eich Exp $ */ - #ifndef __NV_INCLUDE_H__ #define __NV_INCLUDE_H__ commit 22020457f43eceaf26532ecb50e46d743f4a691f Author: Francisco Jerez <curroje...@riseup.net> Date: Tue Oct 26 00:24:06 2010 +0200 dri2: Fix throttling on occluded drawables. Signed-off-by: Francisco Jerez <curroje...@riseup.net> diff --git a/src/nouveau_dri2.c b/src/nouveau_dri2.c index 65e7340..204ab32 100644 --- a/src/nouveau_dri2.c +++ b/src/nouveau_dri2.c @@ -239,6 +239,13 @@ nouveau_dri2_finish_swap(DrawablePtr draw, unsigned int frame, DamageRegionProcessPending(draw); } else { type = DRI2_BLIT_COMPLETE; + + /* Reference the front buffer to let throttling work + * on occluded drawables. */ + WAIT_RING(chan, 1); + OUT_RELOC(chan, dst_bo, 0, + NOUVEAU_BO_VRAM | NOUVEAU_BO_RD, 0, 0); + REGION_TRANSLATE(0, ®, -draw->x, -draw->y); nouveau_dri2_copy_region(draw, ®, s->dst, s->src); } commit 9737a812aacbc544b93eeaa031cf1c2e8adbd661 Author: Ben Skeggs <bske...@redhat.com> Date: Mon Oct 25 10:37:08 2010 +1000 kms: initial pass at supporting zaphod-mode This works ok from some simple testing, there's undoubtedly things that will need polishing still however. Signed-off-by: Ben Skeggs <bske...@redhat.com> diff --git a/man/nouveau.man b/man/nouveau.man index a8961ad..39de690 100644 --- a/man/nouveau.man +++ b/man/nouveau.man @@ -80,6 +80,16 @@ Enable or disable wfb, only affects nv50+. Useful for some legacy configurations 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. +.TP +.BI "Option \*qZaphodHeads\*q \*q" string \*q +Specify the randr output(s) to use with zaphod mode for a particular driver +instance. If you use this option you most use this option for all instances +of the driver. +.br +For example: +.B +Option \*qZaphodHeads\*q \*qLVDS,VGA-0\*q +will assign xrandr outputs LVDS and VGA-0 to this instance of the driver. .SH "SEE ALSO" __xservername__(__appmansuffix__), __xconfigfile__(__filemansuffix__), Xserver(__appmansuffix__), X(__miscmansuffix__) .SH AUTHORS diff --git a/src/drmmode_display.c b/src/drmmode_display.c index 94b19ea..c5b57eb 100644 --- a/src/drmmode_display.c +++ b/src/drmmode_display.c @@ -945,13 +945,48 @@ const char *output_names[] = { "None", }; #define NUM_OUTPUT_NAMES (sizeof(output_names) / sizeof(output_names[0])) +static Bool +drmmode_zaphod_match(ScrnInfoPtr pScrn, const char *s, char *output_name) +{ + int i = 0; + char s1[20]; + + do { + switch(*s) { + case ',': + s1[i] = '\0'; + i = 0; + if (strcmp(s1, output_name) == 0) + return TRUE; + break; + case ' ': + case '\t': + case '\n': + case '\r': + break; + default: + s1[i] = *s; + i++; + break; + } + } while(*s++); + + s1[i] = '\0'; + if (strcmp(s1, output_name) == 0) + return TRUE; + + return FALSE; +} + static void drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num) { + NVPtr pNv = NVPTR(pScrn); xf86OutputPtr output; drmModeConnectorPtr koutput; drmModeEncoderPtr kencoder; drmmode_output_private_ptr drmmode_output; + const char *s; char name[32]; koutput = drmModeGetConnector(drmmode->fd, @@ -973,6 +1008,28 @@ drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num) output_names[koutput->connector_type], koutput->connector_type_id); + if (xf86IsEntityShared(pScrn->entityList[0])) { + s = xf86GetOptValString(pNv->Options, OPTION_ZAPHOD_HEADS); + if (s) { + if (!drmmode_zaphod_match(pScrn, s, name)) { + drmModeFreeEncoder(kencoder); + drmModeFreeConnector(koutput); + return; + } + } else { + if (pNv->Primary && (num != 0)) { + drmModeFreeEncoder(kencoder); + drmModeFreeConnector(koutput); + return; + } else + if (pNv->Secondary && (num != 1)) { + drmModeFreeEncoder(kencoder); + drmModeFreeConnector(koutput); + return; + } + } + } + output = xf86OutputCreate (pScrn, &drmmode_output_funcs, name); if (!output) { drmModeFreeEncoder(kencoder); @@ -1003,8 +1060,6 @@ drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num) output->interlaceAllowed = true; output->doubleScanAllowed = true; - - return; } static Bool @@ -1121,8 +1176,11 @@ Bool drmmode_pre_init(ScrnInfoPtr pScrn, int fd, int cpp) xf86CrtcSetSizeRange(pScrn, 320, 200, drmmode->mode_res->max_width, drmmode->mode_res->max_height); - for (i = 0; i < drmmode->mode_res->count_crtcs; i++) - drmmode_crtc_init(pScrn, drmmode, i); + for (i = 0; i < drmmode->mode_res->count_crtcs; i++) { + if (!xf86IsEntityShared(pScrn->entityList[0] || + pScrn->confScreen->device->screen == i)) + drmmode_crtc_init(pScrn, drmmode, i); + } for (i = 0; i < drmmode->mode_res->count_connectors; i++) drmmode_output_init(pScrn, drmmode, i); diff --git a/src/nv_const.h b/src/nv_const.h index c355cad..f80d125 100644 --- a/src/nv_const.h +++ b/src/nv_const.h @@ -15,6 +15,7 @@ typedef enum { OPTION_VIDEO_KEY, OPTION_WFB, OPTION_GLX_VBLANK, + OPTION_ZAPHOD_HEADS, } NVOpts; @@ -26,6 +27,7 @@ static const OptionInfoRec NVOptions[] = { { OPTION_VIDEO_KEY, "VideoKey", OPTV_INTEGER, {0}, FALSE }, { OPTION_WFB, "WrappedFB", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_GLX_VBLANK, "GLXVBlank", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_ZAPHOD_HEADS, "ZaphodHeads", OPTV_STRING, {0}, FALSE }, { -1, NULL, OPTV_NONE, {0}, FALSE } }; diff --git a/src/nv_driver.c b/src/nv_driver.c index fad7d6a..f351fac 100644 --- a/src/nv_driver.c +++ b/src/nv_driver.c @@ -205,6 +205,7 @@ NVPciProbe(DriverPtr drv, int entity_num, struct pci_device *pci_dev, { -1, -1, NULL } }; struct nouveau_device *dev = NULL; + EntityInfoPtr pEnt = NULL; ScrnInfoPtr pScrn = NULL; drmVersion *version; int chipset, ret; @@ -280,6 +281,12 @@ NVPciProbe(DriverPtr drv, int entity_num, struct pci_device *pci_dev, pScrn->LeaveVT = NVLeaveVT; pScrn->FreeScreen = NVFreeScreen; + xf86SetEntitySharable(entity_num); + + pEnt = xf86GetEntityInfo(entity_num); + xf86SetEntityInstanceForScreen(pScrn, pEnt->index, xf86GetNumEntityInstances(pEnt->index) - 1); + free(pEnt); + return TRUE; } @@ -628,10 +635,18 @@ NVPreInit(ScrnInfoPtr pScrn, int flags) pNv->pEnt = xf86GetEntityInfo(pScrn->entityList[0]); if (pNv->pEnt->location.type != BUS_PCI) return FALSE; - + + if (xf86IsEntityShared(pScrn->entityList[0])) { + if(!xf86IsPrimInitDone(pScrn->entityList[0])) { + pNv->Primary = TRUE; + xf86SetPrimInitDone(pScrn->entityList[0]); + } else { + pNv->Secondary = TRUE; + } + } + /* Find the PCI info for this screen */ pNv->PciInfo = xf86GetPciInfoForEntity(pNv->pEnt->index); - pNv->Primary = xf86IsPrimaryPci(pNv->PciInfo); /* Initialise the kernel module */ if (!NVPreInitDRM(pScrn)) diff --git a/src/nv_type.h b/src/nv_type.h index 94c385a..4204556 100644 --- a/src/nv_type.h +++ b/src/nv_type.h @@ -33,6 +33,7 @@ typedef struct _NVRec { EntityInfoPtr pEnt; struct pci_device *PciInfo; Bool Primary; + Bool Secondary; /* Various pinned memory regions */ struct nouveau_bo * scanout; commit d40c16f5497739c0215f37566db1651a74cb20ba Author: Francisco Jerez <curroje...@riseup.net> Date: Sat Oct 23 02:20:30 2010 +0200 dri2: Fix build on X server 1.8. Signed-off-by: Francisco Jerez <curroje...@riseup.net> diff --git a/src/nouveau_dri2.c b/src/nouveau_dri2.c index 35146f2..65e7340 100644 --- a/src/nouveau_dri2.c +++ b/src/nouveau_dri2.c @@ -201,8 +201,8 @@ nouveau_dri2_finish_swap(DrawablePtr draw, unsigned int frame, RegionRec reg; int type, ret; - RegionInit(®, &(BoxRec){ 0, 0, draw->width, draw->height }, 0); - RegionTranslate(®, draw->x, draw->y); + REGION_INIT(0, ®, (&(BoxRec){ 0, 0, draw->width, draw->height }), 0); + REGION_TRANSLATE(0, ®, draw->x, draw->y); /* Throttle on the previous frame before swapping */ nouveau_bo_map(dst_bo, NOUVEAU_BO_RD); @@ -215,16 +215,16 @@ nouveau_dri2_finish_swap(DrawablePtr draw, unsigned int frame, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD, 0, 0); if (pNv->Architecture >= NV_ARCH_50) - NV50SyncToVBlank(dst_pix, RegionExtents(®)); + NV50SyncToVBlank(dst_pix, REGION_EXTENTS(0, ®)); else - NV11SyncToVBlank(dst_pix, RegionExtents(®)); + NV11SyncToVBlank(dst_pix, REGION_EXTENTS(0, ®)); FIRE_RING(chan); } if (can_exchange(draw, dst_pix, src_pix)) { type = DRI2_EXCHANGE_COMPLETE; - DamageRegionAppend (draw, ®); + DamageRegionAppend(draw, ®); if (DRI2CanFlip(draw)) { type = DRI2_FLIP_COMPLETE; @@ -239,7 +239,7 @@ nouveau_dri2_finish_swap(DrawablePtr draw, unsigned int frame, DamageRegionProcessPending(draw); } else { type = DRI2_BLIT_COMPLETE; - RegionTranslate(®, -draw->x, -draw->y); + REGION_TRANSLATE(0, ®, -draw->x, -draw->y); nouveau_dri2_copy_region(draw, ®, s->dst, s->src); } commit a4d580bf05d7aac1d486e5d1ba9a2201c026e5f5 Author: Francisco Jerez <curroje...@riseup.net> Date: Fri Oct 22 23:09:30 2010 +0200 Bump the required X server version to 1.8. Signed-off-by: Francisco Jerez <curroje...@riseup.net> diff --git a/configure.ac b/configure.ac index 1c39923..676c2a4 100644 --- a/configure.ac +++ b/configure.ac @@ -71,7 +71,7 @@ PKG_CHECK_MODULES(LIBDRM_NOUVEAU, libdrm_nouveau) AC_SUBST(LIBDRM_NOUVEAU_CFLAGS) AC_SUBST(LIBDRM_NOUVEAU_LIBS) -PKG_CHECK_MODULES(XORG, [xorg-server >= 1.7] xproto fontsproto libdrm xf86driproto $REQUIRED_MODULES) +PKG_CHECK_MODULES(XORG, [xorg-server >= 1.8] xproto fontsproto libdrm xf86driproto $REQUIRED_MODULES) PKG_CHECK_MODULES(XEXT, [xextproto >= 7.0.99.1], HAVE_XEXTPROTO_71="yes"; AC_DEFINE(HAVE_XEXTPROTO_71, 1, [xextproto 7.1 available]), HAVE_XEXTPROTO_71="no") commit d0f2e16bc35660d01d3cd20a770cf8e613ab5323 Author: Francisco Jerez <curroje...@riseup.net> Date: Fri Oct 22 23:06:28 2010 +0200 dri2: Report damage on page-flipped drawables. Signed-off-by: Francisco Jerez <curroje...@riseup.net> diff --git a/src/nouveau_dri2.c b/src/nouveau_dri2.c index b006cfc..35146f2 100644 --- a/src/nouveau_dri2.c +++ b/src/nouveau_dri2.c @@ -224,6 +224,7 @@ nouveau_dri2_finish_swap(DrawablePtr draw, unsigned int frame, if (can_exchange(draw, dst_pix, src_pix)) { type = DRI2_EXCHANGE_COMPLETE; + DamageRegionAppend (draw, ®); if (DRI2CanFlip(draw)) { type = DRI2_FLIP_COMPLETE; @@ -235,6 +236,7 @@ nouveau_dri2_finish_swap(DrawablePtr draw, unsigned int frame, SWAP(s->dst->name, s->src->name); SWAP(nouveau_pixmap(dst_pix)->bo, nouveau_pixmap(src_pix)->bo); + DamageRegionProcessPending(draw); } else { type = DRI2_BLIT_COMPLETE; RegionTranslate(®, -draw->x, -draw->y); commit c61e8d03161adcfbba4162172153814accf9e86b Author: Francisco Jerez <curroje...@riseup.net> Date: Fri Oct 22 23:05:24 2010 +0200 Make the sync-to-vblank helpers take a box as argument. Signed-off-by: Francisco Jerez <curroje...@riseup.net> diff --git a/src/nouveau_dri2.c b/src/nouveau_dri2.c index c8d5c57..b006cfc 100644 --- a/src/nouveau_dri2.c +++ b/src/nouveau_dri2.c @@ -198,26 +198,26 @@ nouveau_dri2_finish_swap(DrawablePtr draw, unsigned int frame, struct nouveau_bo *dst_bo = nouveau_pixmap_bo(dst_pix); struct nouveau_bo *src_bo = nouveau_pixmap_bo(src_pix); struct nouveau_channel *chan = pNv->chan; + RegionRec reg; int type, ret; + RegionInit(®, &(BoxRec){ 0, 0, draw->width, draw->height }, 0); + RegionTranslate(®, draw->x, draw->y); + /* Throttle on the previous frame before swapping */ nouveau_bo_map(dst_bo, NOUVEAU_BO_RD); nouveau_bo_unmap(dst_bo); if (can_sync_to_vblank(draw)) { - int x1 = draw->x, y1 = draw->y, - x2 = draw->x + draw->width, - y2 = draw->y + draw->height; - /* Reference the back buffer to sync it to vblank */ WAIT_RING(chan, 1); OUT_RELOC(chan, src_bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD, 0, 0); if (pNv->Architecture >= NV_ARCH_50) - NV50SyncToVBlank(dst_pix, x1, y1, x2, y2); + NV50SyncToVBlank(dst_pix, RegionExtents(®)); else - NV11SyncToVBlank(dst_pix, x1, y1, x2, y2); + NV11SyncToVBlank(dst_pix, RegionExtents(®)); FIRE_RING(chan); } @@ -236,13 +236,9 @@ nouveau_dri2_finish_swap(DrawablePtr draw, unsigned int frame, SWAP(nouveau_pixmap(dst_pix)->bo, nouveau_pixmap(src_pix)->bo); } else { - BoxRec box = { 0, 0, draw->width, draw->height }; - RegionRec region; - - RegionInit(®ion, &box, 0); - type = DRI2_BLIT_COMPLETE; - nouveau_dri2_copy_region(draw, ®ion, s->dst, s->src); + RegionTranslate(®, -draw->x, -draw->y); + nouveau_dri2_copy_region(draw, ®, s->dst, s->src); } /* diff --git a/src/nv04_xv_blit.c b/src/nv04_xv_blit.c index 55d82c4..be39c0d 100644 --- a/src/nv04_xv_blit.c +++ b/src/nv04_xv_blit.c @@ -130,8 +130,7 @@ NVPutBlitImage(ScrnInfoPtr pScrn, struct nouveau_bo *src, int src_offset, if(pPriv->SyncToVBlank) { FIRE_RING(chan); - NV11SyncToVBlank(ppix, dstBox->x1, dstBox->y1, - dstBox->x2, dstBox->y2); + NV11SyncToVBlank(ppix, dstBox); } if (pNv->dev->chipset >= 0x05) { diff --git a/src/nv30_xv_tex.c b/src/nv30_xv_tex.c index 61558e9..ffa68e4 100644 --- a/src/nv30_xv_tex.c +++ b/src/nv30_xv_tex.c @@ -350,8 +350,7 @@ NV30PutTextureImage(ScrnInfoPtr pScrn, struct nouveau_bo *src, int src_offset, /* Just before rendering we wait for vblank in the non-composited case. */ if (pPriv->SyncToVBlank) { FIRE_RING(chan); - NV11SyncToVBlank(ppix, dstBox->x1, dstBox->y1, - dstBox->x2, dstBox->y2); + NV11SyncToVBlank(ppix, dstBox); } /* These are fixed point values in the 16.16 format. */ diff --git a/src/nv40_xv_tex.c b/src/nv40_xv_tex.c index 602bb7a..e0444e8 100644 --- a/src/nv40_xv_tex.c +++ b/src/nv40_xv_tex.c @@ -339,8 +339,7 @@ NV40PutTextureImage(ScrnInfoPtr pScrn, /* Just before rendering we wait for vblank in the non-composited case. */ if (pPriv->SyncToVBlank) { FIRE_RING(chan); - NV11SyncToVBlank(ppix, dstBox->x1, dstBox->y1, - dstBox->x2, dstBox->y2); + NV11SyncToVBlank(ppix, dstBox); } /* These are fixed point values in the 16.16 format. */ diff --git a/src/nv50_accel.c b/src/nv50_accel.c index d0def57..95d1886 100644 --- a/src/nv50_accel.c +++ b/src/nv50_accel.c @@ -24,7 +24,7 @@ #include "nv50_accel.h" void -NV50SyncToVBlank(PixmapPtr ppix, int x1, int y1, int x2, int y2) +NV50SyncToVBlank(PixmapPtr ppix, BoxPtr box) { ScrnInfoPtr pScrn = xf86Screens[ppix->drawable.pScreen->myNum]; NVPtr pNv = NVPTR(pScrn); @@ -35,7 +35,9 @@ NV50SyncToVBlank(PixmapPtr ppix, int x1, int y1, int x2, int y2) if (!nouveau_exa_pixmap_is_onscreen(ppix)) return; - crtcs = nv_window_belongs_to_crtc(pScrn, x1, y1, x2 - x1, y2 - y1); + crtcs = nv_window_belongs_to_crtc(pScrn, box->x1, box->y1, + box->x2 - box->x1, + box->y2 - box->y1); if (!crtcs) return; diff --git a/src/nv50_xv.c b/src/nv50_xv.c index 87e22b5..e02f86d 100644 --- a/src/nv50_xv.c +++ b/src/nv50_xv.c @@ -289,8 +289,7 @@ nv50_xv_image_put(ScrnInfoPtr pScrn, return BadAlloc; if (pPriv->SyncToVBlank) { - NV50SyncToVBlank(ppix, dstBox->x1, dstBox->y1, - dstBox->x2, dstBox->y2); + NV50SyncToVBlank(ppix, dstBox); } /* These are fixed point values in the 16.16 format. */ diff --git a/src/nv_accel_common.c b/src/nv_accel_common.c index 3739c79..1ade291 100644 --- a/src/nv_accel_common.c +++ b/src/nv_accel_common.c @@ -90,7 +90,7 @@ nouveau_allocate_surface(ScrnInfoPtr scrn, int width, int height, int bpp, } void -NV11SyncToVBlank(PixmapPtr ppix, int x1, int y1, int x2, int y2) +NV11SyncToVBlank(PixmapPtr ppix, BoxPtr box) { ScrnInfoPtr pScrn = xf86Screens[ppix->drawable.pScreen->myNum]; NVPtr pNv = NVPTR(pScrn); @@ -101,7 +101,9 @@ NV11SyncToVBlank(PixmapPtr ppix, int x1, int y1, int x2, int y2) if (!nouveau_exa_pixmap_is_onscreen(ppix)) return; - crtcs = nv_window_belongs_to_crtc(pScrn, x1, y1, x2 - x1, y2 - y1); + crtcs = nv_window_belongs_to_crtc(pScrn, box->x1, box->y1, + box->x2 - box->x1, + box->y2 - box->y1); if (!crtcs) return; diff --git a/src/nv_proto.h b/src/nv_proto.h index 8514af9..888e74e 100644 --- a/src/nv_proto.h +++ b/src/nv_proto.h @@ -17,7 +17,7 @@ Bool NVAccelGetCtxSurf2DFormatFromPixmap(PixmapPtr pPix, int *fmt_ret); Bool NVAccelGetCtxSurf2DFormatFromPicture(PicturePtr pPix, int *fmt_ret); PixmapPtr NVGetDrawablePixmap(DrawablePtr pDraw); void NVAccelFree(ScrnInfoPtr pScrn); -void NV11SyncToVBlank(PixmapPtr ppix, int x1, int y1, int x2, int y2); +void NV11SyncToVBlank(PixmapPtr ppix, BoxPtr box); Bool nouveau_allocate_surface(ScrnInfoPtr scrn, int width, int height, int bpp, int usage_hint, int *pitch, struct nouveau_bo **bo); @@ -132,7 +132,7 @@ int NV40GetTexturePortAttribute(ScrnInfoPtr, Atom, INT32 *, pointer); int NV40SetTexturePortAttribute(ScrnInfoPtr, Atom, INT32, pointer); /* in nv50_accel.c */ -void NV50SyncToVBlank(PixmapPtr ppix, int x1, int y1, int x2, int y2); +void NV50SyncToVBlank(PixmapPtr ppix, BoxPtr box); Bool NVAccelInitNV50TCL(ScrnInfoPtr pScrn); /* in nv50_exa.c */ commit a685a5c3be12f3e95a6ec1140af115e7ef28fcaa Author: Francisco Jerez <curroje...@riseup.net> Date: Wed Oct 13 18:45:04 2010 +0200 dri2: Implement the ScheduleWaitMSC/GetMSC hooks. Signed-off-by: Francisco Jerez <curroje...@riseup.net> diff --git a/src/nouveau_dri2.c b/src/nouveau_dri2.c index 7fdfa9c..c8d5c57 100644 --- a/src/nouveau_dri2.c +++ b/src/nouveau_dri2.c @@ -116,7 +116,8 @@ nouveau_dri2_copy_region(DrawablePtr pDraw, RegionPtr pRegion, struct nouveau_dri2_vblank_state { enum { - SWAP + SWAP, + WAIT } action; ClientPtr client; @@ -308,6 +309,66 @@ fail: return FALSE; } +static Bool +nouveau_dri2_schedule_wait(ClientPtr client, DrawablePtr draw, + CARD64 target_msc, CARD64 divisor, CARD64 remainder) +{ + struct nouveau_dri2_vblank_state *s; + CARD64 current_msc; + int ret; + + if (!can_sync_to_vblank(draw)) + return FALSE; + + /* Initialize a vblank structure */ + s = malloc(sizeof(*s)); + if (!s) + return FALSE; + + *s = (struct nouveau_dri2_vblank_state) { WAIT, client, draw->id }; + + /* Get current sequence */ + ret = nouveau_wait_vblank(draw, DRM_VBLANK_RELATIVE, 0, + ¤t_msc, NULL, NULL); + if (ret) + goto fail; + + /* Calculate a wait target if we don't have one */ + if (current_msc > target_msc && divisor) + target_msc = current_msc + divisor + - (current_msc - remainder) % divisor; + + /* Request a vblank event */ + ret = nouveau_wait_vblank(draw, DRM_VBLANK_ABSOLUTE | + DRM_VBLANK_EVENT, + max(current_msc, target_msc), + NULL, NULL, s); + if (ret) + goto fail; + + DRI2BlockClient(client, draw); + return TRUE; +fail: + free(s); + return FALSE; +} + +static Bool +nouveau_dri2_get_msc(DrawablePtr draw, CARD64 *ust, CARD64 *msc) +{ + int ret; + + if (!can_sync_to_vblank(draw)) + return FALSE; + + /* Get current sequence */ + ret = nouveau_wait_vblank(draw, DRM_VBLANK_RELATIVE, 0, msc, ust, NULL); + if (ret) + return FALSE; + + return TRUE; +} + void nouveau_dri2_vblank_handler(int fd, unsigned int frame, unsigned int tv_sec, unsigned int tv_usec, @@ -326,6 +387,11 @@ nouveau_dri2_vblank_handler(int fd, unsigned int frame, case SWAP: nouveau_dri2_finish_swap(draw, frame, tv_sec, tv_usec, s); break; + + case WAIT: + DRI2WaitMSCComplete(s->client, draw, frame, tv_sec, tv_usec); + free(s); + break; } } @@ -349,6 +415,8 @@ nouveau_dri2_init(ScreenPtr pScreen) dri2.DestroyBuffer = nouveau_dri2_destroy_buffer; dri2.CopyRegion = nouveau_dri2_copy_region; dri2.ScheduleSwap = nouveau_dri2_schedule_swap; + dri2.ScheduleWaitMSC = nouveau_dri2_schedule_wait; + dri2.GetMSC = nouveau_dri2_get_msc; return DRI2ScreenInit(pScreen, &dri2); } commit eb83c830c87bce345748edef3b50660246143db7 Author: Francisco Jerez <curroje...@riseup.net> Date: Thu Oct 21 22:57:08 2010 +0200 dri2: Add pageflip/exchange support. Signed-off-by: Francisco Jerez <curroje...@riseup.net> diff --git a/src/drmmode_display.c b/src/drmmode_display.c index 4220cf5..94b19ea 100644 --- a/src/drmmode_display.c +++ b/src/drmmode_display.c @@ -1179,9 +1179,47 @@ drmmode_cursor_init(ScreenPtr pScreen) return xf86_cursors_init(pScreen, size, size, flags); } -#ifdef HAVE_LIBUDEV +Bool +drmmode_page_flip(DrawablePtr draw, PixmapPtr back, void *priv) +{ + ScrnInfoPtr scrn = xf86Screens[draw->pScreen->myNum]; + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); + drmmode_crtc_private_ptr crtc = config->crtc[0]->driver_private; + drmmode_ptr mode = crtc->drmmode; + int ret, i, old_fb_id; + + old_fb_id = mode->fb_id; + ret = drmModeAddFB(mode->fd, scrn->virtualX, scrn->virtualY, + scrn->depth, scrn->bitsPerPixel, + scrn->displayWidth * scrn->bitsPerPixel / 8, + nouveau_pixmap_bo(back)->handle, &mode->fb_id); + if (ret) { + xf86DrvMsg(scrn->scrnIndex, X_WARNING, + "add fb failed: %s\n", strerror(errno)); + return FALSE; + } + + for (i = 0; i < config->num_crtc; i++) { + crtc = config->crtc[i]->driver_private; + if (!config->crtc[i]->enabled) + continue; + ret = drmModePageFlip(mode->fd, crtc->mode_crtc->crtc_id, + mode->fb_id, 0, priv); + if (ret) { + xf86DrvMsg(scrn->scrnIndex, X_WARNING, + "flip queue failed: %s\n", strerror(errno)); + return FALSE; + } + } + + drmModeRmFB(mode->fd, old_fb_id); + + return TRUE; +} + +#ifdef HAVE_LIBUDEV static void drmmode_handle_uevents(ScrnInfoPtr scrn) { diff --git a/src/nouveau_dri2.c b/src/nouveau_dri2.c index 66fe16c..7fdfa9c 100644 --- a/src/nouveau_dri2.c +++ b/src/nouveau_dri2.c @@ -129,6 +129,20 @@ struct nouveau_dri2_vblank_state { }; static Bool +can_exchange(DrawablePtr draw, PixmapPtr dst_pix, PixmapPtr src_pix) +{ + ScrnInfoPtr scrn = xf86Screens[draw->pScreen->myNum]; + NVPtr pNv = NVPTR(scrn); + + return (!nouveau_exa_pixmap_is_onscreen(dst_pix) || + (DRI2CanFlip(draw) && pNv->has_pageflip)) && + dst_pix->drawable.width == src_pix->drawable.width && + dst_pix->drawable.height == src_pix->drawable.height && + dst_pix->drawable.depth == src_pix->drawable.depth && + dst_pix->devKind == src_pix->devKind; +} + +static Bool can_sync_to_vblank(DrawablePtr draw) { ScrnInfoPtr scrn = xf86Screens[draw->pScreen->myNum]; @@ -183,9 +197,7 @@ nouveau_dri2_finish_swap(DrawablePtr draw, unsigned int frame, struct nouveau_bo *dst_bo = nouveau_pixmap_bo(dst_pix); struct nouveau_bo *src_bo = nouveau_pixmap_bo(src_pix); struct nouveau_channel *chan = pNv->chan; - BoxRec box = { 0, 0, draw->width, draw->height }; - RegionRec region; - int ret; + int type, ret; /* Throttle on the previous frame before swapping */ nouveau_bo_map(dst_bo, NOUVEAU_BO_RD); @@ -209,12 +221,40 @@ nouveau_dri2_finish_swap(DrawablePtr draw, unsigned int frame, FIRE_RING(chan); } + if (can_exchange(draw, dst_pix, src_pix)) { + type = DRI2_EXCHANGE_COMPLETE; - RegionInit(®ion, &box, 0); - nouveau_dri2_copy_region(draw, ®ion, s->dst, s->src); + if (DRI2CanFlip(draw)) { + type = DRI2_FLIP_COMPLETE; + ret = drmmode_page_flip(draw, src_pix, s); + if (!ret) + goto out; + } + + SWAP(s->dst->name, s->src->name); + SWAP(nouveau_pixmap(dst_pix)->bo, nouveau_pixmap(src_pix)->bo); + + } else { + BoxRec box = { 0, 0, draw->width, draw->height }; + RegionRec region; + + RegionInit(®ion, &box, 0); + + type = DRI2_BLIT_COMPLETE; + nouveau_dri2_copy_region(draw, ®ion, s->dst, s->src); + } + /* + * Tell the X server buffers are already swapped even if they're + * not, to prevent it from blocking the client on the next + * GetBuffers request (and let the client do triple-buffering). + * + * XXX - The DRI2SwapLimit() API will allow us to move this to + * the flip handler with no FPS hit. + */ DRI2SwapComplete(s->client, draw, frame, tv_sec, tv_usec, - DRI2_BLIT_COMPLETE, s->func, s->data); + type, s->func, s->data); +out: free(s); } diff --git a/src/nouveau_local.h b/src/nouveau_local.h index 5d3200a..38b861f 100644 --- a/src/nouveau_local.h +++ b/src/nouveau_local.h @@ -74,4 +74,10 @@ static inline int round_down_pow2(int x) return 1 << log2i(x); } +#define SWAP(x, y) do { \ + typeof(x) __z = (x); \ + (x) = (y); \ + (y) = __z; \ + } while (0) + #endif diff --git a/src/nv_driver.c b/src/nv_driver.c index 5ef7984..fad7d6a 100644 --- a/src/nv_driver.c +++ b/src/nv_driver.c @@ -28,6 +28,7 @@ #include "xf86int10.h" #include "xf86drm.h" #include "xf86drmMode.h" +#include "nouveau_drm.h" /* * Forward definitions for the functions that make up the driver. @@ -586,6 +587,7 @@ NVPreInit(ScrnInfoPtr pScrn, int flags) struct nouveau_device *dev; NVPtr pNv; MessageType from; + uint64_t v; int ret, i; if (flags & PROBE_DETECT) { @@ -792,6 +794,15 @@ NVPreInit(ScrnInfoPtr pScrn, int flags) pNv->glx_vblank ? "enabled" : "disabled"); } +#ifdef NOUVEAU_GETPARAM_HAS_PAGEFLIP + ret = nouveau_device_get_param(pNv->dev, + NOUVEAU_GETPARAM_HAS_PAGEFLIP, &v); + if (!ret) + pNv->has_pageflip = v; +#else + (void)v; +#endif + if(xf86GetOptValInteger(pNv->Options, OPTION_VIDEO_KEY, &(pNv->videoKey))) { xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "video key set to 0x%x\n", pNv->videoKey); diff --git a/src/nv_proto.h b/src/nv_proto.h index ba234b3..8514af9 100644 --- a/src/nv_proto.h +++ b/src/nv_proto.h @@ -7,6 +7,7 @@ void drmmode_adjust_frame(ScrnInfoPtr pScrn, int x, int y, int flags); void drmmode_remove_fb(ScrnInfoPtr pScrn); Bool drmmode_cursor_init(ScreenPtr pScreen); void drmmode_fbcon_copy(ScreenPtr pScreen); +Bool drmmode_page_flip(DrawablePtr draw, PixmapPtr back, void *priv); void drmmode_screen_init(ScreenPtr pScreen); void drmmode_screen_fini(ScreenPtr pScreen); diff --git a/src/nv_type.h b/src/nv_type.h index a9c693f..94c385a 100644 --- a/src/nv_type.h +++ b/src/nv_type.h @@ -51,6 +51,7 @@ typedef struct _NVRec { Bool wfb_enabled; Bool tiled_scanout; Bool glx_vblank; + Bool has_pageflip; ScreenBlockHandlerProcPtr BlockHandler; CreateScreenResourcesProcPtr CreateScreenResources; CloseScreenProcPtr CloseScreen; commit c88f13e25b0040c1dd0f93e0ac40f62a6005ce59 Author: Francisco Jerez <curroje...@riseup.net> Date: Thu Oct 14 22:25:50 2010 +0200 Allocate a tiled scanout on pre-nv50 too. Pageflip between tiled and non-tiled surfaces isn't such a good idea. -- To UNSUBSCRIBE, email to debian-x-requ...@lists.debian.org with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org Archive: http://lists.debian.org/e1psx4u-00050i...@alioth.debian.org