From 321eb2df5c8b1da4d6469037dd1d8888b508fabd Mon Sep 17 00:00:00 2001 From: Francisco Jerez Date: Wed, 4 Aug 2010 13:11:24 +0200 Subject: Revert "nv04-nv40/exa: Match the blob behavior more closely on PrepareCopy." This reverts commit 9de0d97bd2fc2ee8800d48b5340a3d495525ad3e. Unnecessary after kernel commit "drm/nouveau: Ack the context switch interrupt before switching contexts.". --- src/nv04_exa.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/nv04_exa.c b/src/nv04_exa.c index c5e44a5..19c5fc5 100644 --- a/src/nv04_exa.c +++ b/src/nv04_exa.c @@ -207,15 +207,11 @@ NV04EXAPrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, int dx, int dy, return FALSE; } - BEGIN_RING(chan, blit, NV04_IMAGE_BLIT_SURFACE, 1); - OUT_RING (chan, pNv->NvContextSurfaces->handle); BEGIN_RING(chan, blit, NV01_IMAGE_BLIT_OPERATION, 1); OUT_RING (chan, 1); /* ROP_AND */ NV04EXASetROP(pScrn, alu, planemask); } else { - BEGIN_RING(chan, blit, NV04_IMAGE_BLIT_SURFACE, 1); - OUT_RING (chan, pNv->NvContextSurfaces->handle); BEGIN_RING(chan, blit, NV01_IMAGE_BLIT_OPERATION, 1); OUT_RING (chan, 3); /* SRCCOPY */ } -- cgit v1.2.1 From b96170a4e51c1d3167601210ca31e98283c02885 Mon Sep 17 00:00:00 2001 From: Francisco Jerez Date: Thu, 5 Aug 2010 00:40:40 +0200 Subject: nv10/exa: Bump maxX/maxY to 4096/4096. This way we can do accelerated 2D on larger pixmaps, it will still fall back to software when we hit the 2048x2048 texturing limit in a composite operation. --- src/nouveau_exa.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/nouveau_exa.c b/src/nouveau_exa.c index 1b8888e..80d0338 100644 --- a/src/nouveau_exa.c +++ b/src/nouveau_exa.c @@ -524,7 +524,7 @@ nouveau_exa_init(ScreenPtr pScreen) exa->maxX = 8192; exa->maxY = 8192; } else - if (pNv->Architecture >= NV_ARCH_20) { + if (pNv->Architecture >= NV_ARCH_10) { exa->maxX = 4096; exa->maxY = 4096; } else { -- cgit v1.2.1 From 9f50b62229d5984ee5c16bc54953c7f8e2d5e575 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Fri, 6 Aug 2010 08:28:34 +1000 Subject: nvc0: recognise these chipsets, and allow NoAccel mode on them Signed-off-by: Ben Skeggs --- src/nv_driver.c | 8 ++++++-- src/nv_type.h | 1 + 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/nv_driver.c b/src/nv_driver.c index 0abe400..3c16918 100644 --- a/src/nv_driver.c +++ b/src/nv_driver.c @@ -254,6 +254,7 @@ NVPciProbe(DriverPtr drv, int entity_num, struct pci_device *pci_dev, case 0x80: case 0x90: case 0xa0: + case 0xc0: break; default: xf86DrvMsg(-1, X_ERROR, "Unknown chipset: NV%02x\n", chipset); @@ -652,6 +653,9 @@ NVPreInit(ScrnInfoPtr pScrn, int flags) case 0xa0: pNv->Architecture = NV_ARCH_50; break; + case 0xc0: + pNv->Architecture = NV_ARCH_C0; + break; default: return FALSE; } @@ -674,8 +678,8 @@ NVPreInit(ScrnInfoPtr pScrn, int flags) break; case 30: /* OK on NV50 KMS */ - if (pNv->Architecture != NV_ARCH_50) - NVPreInitFail("Depth 30 supported on G80 only\n"); + if (pNv->Architecture < NV_ARCH_50) + NVPreInitFail("Depth 30 supported on G80+ only\n"); break; case 15: /* 15 may get done one day, so leave any code for it in place */ default: diff --git a/src/nv_type.h b/src/nv_type.h index 0bfe721..9c22ea9 100644 --- a/src/nv_type.h +++ b/src/nv_type.h @@ -24,6 +24,7 @@ #define NV_ARCH_30 0x30 #define NV_ARCH_40 0x40 #define NV_ARCH_50 0x50 +#define NV_ARCH_C0 0xc0 /* NV50 */ typedef struct _NVRec *NVPtr; -- cgit v1.2.1 From 1cb6c91a9afe88d73f8a1180b00f56a9150a16ed Mon Sep 17 00:00:00 2001 From: Roy Spliet Date: Sat, 7 Aug 2010 20:59:06 +0200 Subject: nouveau_exa.c: move line_count logic out of UTS/DFS loop Signed-off-by: Roy Spliet Signed-off-by: Maarten Maathuis --- src/nouveau_exa.c | 39 ++++++++++++++++----------------------- 1 file changed, 16 insertions(+), 23 deletions(-) diff --git a/src/nouveau_exa.c b/src/nouveau_exa.c index 80d0338..3b2c9be 100644 --- a/src/nouveau_exa.c +++ b/src/nouveau_exa.c @@ -52,6 +52,8 @@ NVAccelDownloadM2MF(PixmapPtr pspix, int x, int y, int w, int h, unsigned cpp = pspix->drawable.bitsPerPixel / 8; unsigned line_len = w * cpp; unsigned src_offset = 0, src_pitch = 0, linear = 0; + /* Maximum DMA transfer */ + unsigned line_count = pNv->GART->size / line_len; if (!nv50_style_tiled_pixmap(pspix)) { linear = 1; @@ -59,21 +61,16 @@ NVAccelDownloadM2MF(PixmapPtr pspix, int x, int y, int w, int h, src_offset += (y * src_pitch) + (x * cpp); } + /* HW limitations */ + if (line_count > 2047) + line_count = 2047; + while (h) { - int line_count, i; + int i; char *src; - if (h * line_len <= pNv->GART->size) { + if (line_count > h) line_count = h; - } else { - line_count = pNv->GART->size / line_len; - if (line_count > h) - line_count = h; - } - - /* HW limitations */ - if (line_count > 2047) - line_count = 2047; if (MARK_RING(chan, 32, 6)) return FALSE; @@ -169,6 +166,8 @@ NVAccelUploadM2MF(PixmapPtr pdpix, int x, int y, int w, int h, unsigned cpp = pdpix->drawable.bitsPerPixel / 8; unsigned line_len = w * cpp; unsigned dst_offset = 0, dst_pitch = 0, linear = 0; + /* Maximum DMA transfer */ + unsigned line_count = pNv->GART->size / line_len; if (!nv50_style_tiled_pixmap(pdpix)) { linear = 1; @@ -176,22 +175,16 @@ NVAccelUploadM2MF(PixmapPtr pdpix, int x, int y, int w, int h, dst_offset += (y * dst_pitch) + (x * cpp); } + /* HW limitations */ + if (line_count > 2047) + line_count = 2047; + while (h) { - int line_count, i; + int i; char *dst; - /* Determine max amount of data we can DMA at once */ - if (h * line_len <= pNv->GART->size) { + if (line_count > h) line_count = h; - } else { - line_count = pNv->GART->size / line_len; - if (line_count > h) - line_count = h; - } - - /* HW limitations */ - if (line_count > 2047) - line_count = 2047; /* Upload to GART */ if (nouveau_bo_map(pNv->GART, NOUVEAU_BO_WR)) -- cgit v1.2.1 From f5b486dd237679aec1987985f9ecffc6a4fd3105 Mon Sep 17 00:00:00 2001 From: Maarten Maathuis Date: Fri, 13 Aug 2010 22:16:51 +0200 Subject: nv50/xv: We have 18 relocs, not 16, adjust MARK_RING. Signed-off-by: Maarten Maathuis --- src/nv50_xv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/nv50_xv.c b/src/nv50_xv.c index 255fa51..9be8156 100644 --- a/src/nv50_xv.c +++ b/src/nv50_xv.c @@ -70,7 +70,7 @@ nv50_xv_state_emit(PixmapPtr ppix, int id, struct nouveau_bo *src, const unsigned tcb_flags = NOUVEAU_BO_RDWR | NOUVEAU_BO_VRAM; uint32_t mode = 0xd0005000 | (src->tile_mode << 22); - if (MARK_RING(chan, 256, 16)) + if (MARK_RING(chan, 256, 18)) return FALSE; BEGIN_RING(chan, tesla, NV50TCL_RT_ADDRESS_HIGH(0), 5); -- cgit v1.2.1 From 00d390952c912d4e9fc2c962caaeb90bf563d5b1 Mon Sep 17 00:00:00 2001 From: Maarten Maathuis Date: Fri, 13 Aug 2010 22:24:26 +0200 Subject: nv50/xv: Fix the uncommon codepath to use width/height variable. - The common codepath should be the correct one, because that is triggered often, while the other is rare. - This isn't neccesarily a problem, but let's be on the safe side. Signed-off-by: Maarten Maathuis --- src/nv50_xv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/nv50_xv.c b/src/nv50_xv.c index 9be8156..2e0f080 100644 --- a/src/nv50_xv.c +++ b/src/nv50_xv.c @@ -331,7 +331,7 @@ nv50_xv_image_put(ScrnInfoPtr pScrn, if (AVAIL_RING(chan) < 64) { if (!nv50_xv_state_emit(ppix, id, src, packed_y, uv, - src_w, src_h)) + width, height)) return BadAlloc; } -- cgit v1.2.1 From 390f1c86d9583f4ceabd407ee47410073c2a1b55 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Fri, 20 Aug 2010 09:48:32 +1000 Subject: nv50/xv: support UYVY Signed-off-by: Ben Skeggs --- src/nouveau_xv.c | 3 ++- src/nv50_xv.c | 16 ++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/nouveau_xv.c b/src/nouveau_xv.c index 4437aa6..b531f10 100644 --- a/src/nouveau_xv.c +++ b/src/nouveau_xv.c @@ -1983,7 +1983,8 @@ NV50TexturedImages[] = { XVIMAGE_YV12, XVIMAGE_I420, - XVIMAGE_YUY2 + XVIMAGE_YUY2, + XVIMAGE_UYVY }; static XF86VideoAdaptorPtr diff --git a/src/nv50_xv.c b/src/nv50_xv.c index 2e0f080..b9349a2 100644 --- a/src/nv50_xv.c +++ b/src/nv50_xv.c @@ -147,11 +147,19 @@ nv50_xv_state_emit(PixmapPtr ppix, int id, struct nouveau_bo *src, OUT_RING (chan, 0x03000000); OUT_RING (chan, 0x00000000); } else { + if (id == FOURCC_UYVY) { + OUT_RING (chan, NV50TIC_0_0_MAPA_C1 | NV50TIC_0_0_TYPEA_UNORM | + NV50TIC_0_0_MAPB_ZERO | NV50TIC_0_0_TYPEB_UNORM | + NV50TIC_0_0_MAPG_ZERO | NV50TIC_0_0_TYPEG_UNORM | + NV50TIC_0_0_MAPR_ZERO | NV50TIC_0_0_TYPER_UNORM | + NV50TIC_0_0_FMT_8_8); + } else { OUT_RING (chan, NV50TIC_0_0_MAPA_C0 | NV50TIC_0_0_TYPEA_UNORM | NV50TIC_0_0_MAPB_ZERO | NV50TIC_0_0_TYPEB_UNORM | NV50TIC_0_0_MAPG_ZERO | NV50TIC_0_0_TYPEG_UNORM | NV50TIC_0_0_MAPR_ZERO | NV50TIC_0_0_TYPER_UNORM | NV50TIC_0_0_FMT_8_8); + } if (OUT_RELOCl(chan, src, packed_y, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD) || OUT_RELOC (chan, src, packed_y, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | NOUVEAU_BO_HIGH | NOUVEAU_BO_OR, mode, mode)) { @@ -163,11 +171,19 @@ nv50_xv_state_emit(PixmapPtr ppix, int id, struct nouveau_bo *src, OUT_RING (chan, (1 << NV50TIC_0_5_DEPTH_SHIFT) | src_h); OUT_RING (chan, 0x03000000); OUT_RING (chan, 0x00000000); + if (id == FOURCC_UYVY) { + OUT_RING (chan, NV50TIC_0_0_MAPA_C2 | NV50TIC_0_0_TYPEA_UNORM | + NV50TIC_0_0_MAPB_C0 | NV50TIC_0_0_TYPEB_UNORM | + NV50TIC_0_0_MAPG_ZERO | NV50TIC_0_0_TYPEG_UNORM | + NV50TIC_0_0_MAPR_ZERO | NV50TIC_0_0_TYPER_UNORM | + NV50TIC_0_0_FMT_8_8_8_8); + } else { OUT_RING (chan, NV50TIC_0_0_MAPA_C3 | NV50TIC_0_0_TYPEA_UNORM | NV50TIC_0_0_MAPB_C1 | NV50TIC_0_0_TYPEB_UNORM | NV50TIC_0_0_MAPG_ZERO | NV50TIC_0_0_TYPEG_UNORM | NV50TIC_0_0_MAPR_ZERO | NV50TIC_0_0_TYPER_UNORM | NV50TIC_0_0_FMT_8_8_8_8); + } if (OUT_RELOCl(chan, src, packed_y, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD) || OUT_RELOC (chan, src, packed_y, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | NOUVEAU_BO_HIGH | NOUVEAU_BO_OR, mode, mode)) { -- cgit v1.2.1 From 34025f0dc9284873d4bf7e4f547ed69fc562a3c9 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Thu, 26 Aug 2010 13:19:39 +1000 Subject: kickoff from the flush callback chain MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is a port of intel commit: 69d65f9184006eac790efcff78a0e425160e95aa Submit batch buffers from flush callback chain There are a few cases where the server will flush client output buffers but our block handler only catches the most common (before going into select If the server flushes client buffers before we submit our batch buffer, the client may receive a damage event for rendering that hasn't happened yet Instead, we can hook into the flush callback chain, which the server will invoke just before flushing output. This lets us submit batch buffers before sending out events, preserving ordering. Fixes 28438: [bisected] incorrect character in gnome-terminal under compiz https://bugs.freedesktop.org/show_bug.cgi?id=28438 Signed-off-by: Kristian Høgsberg Signed-off-by: Ben Skeggs --- src/nv_driver.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/nv_driver.c b/src/nv_driver.c index 3c16918..bd061ed 100644 --- a/src/nv_driver.c +++ b/src/nv_driver.c @@ -355,6 +355,16 @@ NVLeaveVT(int scrnIndex, int flags) ErrorF("Error dropping master: %d\n", ret); } +static void +NVFlushCallback(CallbackListPtr *list, pointer user_data, pointer call_data) +{ + ScrnInfoPtr pScrn = user_data; + NVPtr pNv = NVPTR(pScrn); + + if (pScrn->vtSema && !pNv->NoAccel) + FIRE_RING (pNv->chan); +} + static void NVBlockHandler ( int i, @@ -367,9 +377,6 @@ NVBlockHandler ( ScrnInfoPtr pScrnInfo = xf86Screens[i]; NVPtr pNv = NVPTR(pScrnInfo); - if (pScrnInfo->vtSema && !pNv->NoAccel) - FIRE_RING (pNv->chan); - pScreen->BlockHandler = pNv->BlockHandler; (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask); pScreen->BlockHandler = NVBlockHandler; @@ -432,6 +439,8 @@ NVCloseScreen(int scrnIndex, ScreenPtr pScreen) xf86_cursors_fini(pScreen); + DeleteCallback(&FlushCallback, NVFlushCallback, pScrn); + if (pNv->ShadowPtr) { free(pNv->ShadowPtr); pNv->ShadowPtr = NULL; @@ -1146,6 +1155,9 @@ NVScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) pNv->BlockHandler = pScreen->BlockHandler; pScreen->BlockHandler = NVBlockHandler; + if (!AddCallback(&FlushCallback, NVFlushCallback, pScrn)) + return FALSE; + pScrn->vtSema = TRUE; pScrn->pScreen = pScreen; -- cgit v1.2.1 From 065576d5df0df4da61050d789f548801656b62d5 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Thu, 26 Aug 2010 13:22:33 +1000 Subject: dri2: remove explit flush from copy_region() Unnecessary now that we kickoff from within the flush callback chain. Signed-off-by: Ben Skeggs --- src/nouveau_dri2.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/nouveau_dri2.c b/src/nouveau_dri2.c index f7675fc..2666506 100644 --- a/src/nouveau_dri2.c +++ b/src/nouveau_dri2.c @@ -93,7 +93,6 @@ nouveau_dri2_copy_region(DrawablePtr pDraw, RegionPtr pRegion, PixmapPtr pspix = src->ppix, pdpix = dst->ppix; ScreenPtr pScreen = pDraw->pScreen; ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - NVPtr pNv = NVPTR(pScrn); RegionPtr pCopyClip; GCPtr pGC; @@ -112,8 +111,6 @@ nouveau_dri2_copy_region(DrawablePtr pDraw, RegionPtr pRegion, pDraw->width, pDraw->height, 0, 0); FreeScratchGC(pGC); - - FIRE_RING(pNv->chan); } Bool -- cgit v1.2.1 From 14c93acfc3fde04415e1c6a2a056465d15c86315 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Fri, 17 Sep 2010 13:17:37 +1000 Subject: noaccel: fix rotation, as well as an assert during server shutdown Signed-off-by: Ben Skeggs --- src/drmmode_display.c | 24 ++++++++++++++++-------- src/nouveau_dri2.c | 1 - src/nv_driver.c | 3 ++- 3 files changed, 18 insertions(+), 10 deletions(-) diff --git a/src/drmmode_display.c b/src/drmmode_display.c index 9b5d52d..011f4dd 100644 --- a/src/drmmode_display.c +++ b/src/drmmode_display.c @@ -87,17 +87,22 @@ static void drmmode_output_dpms(xf86OutputPtr output, int mode); static PixmapPtr drmmode_pixmap_wrap(ScreenPtr pScreen, int width, int height, int depth, - int bpp, int pitch, struct nouveau_bo *bo) + int bpp, int pitch, struct nouveau_bo *bo, void *data) { + NVPtr pNv = NVPTR(xf86Screens[pScreen->myNum]); PixmapPtr ppix; + if (!pNv->NoAccel) + data = NULL; + ppix = pScreen->CreatePixmap(pScreen, 0, 0, depth, 0); if (!ppix) return NULL; pScreen->ModifyPixmapHeader(ppix, width, height, depth, bpp, - pitch, NULL); - nouveau_bo_ref(bo, &nouveau_pixmap(ppix)->bo); + pitch, data); + if (!pNv->NoAccel) + nouveau_bo_ref(bo, &nouveau_pixmap(ppix)->bo); return ppix; } @@ -224,7 +229,7 @@ drmmode_fbcon_copy(ScreenPtr pScreen) } pspix = drmmode_pixmap_wrap(pScreen, fb->width, fb->height, - fb->depth, fb->bpp, fb->pitch, bo); + fb->depth, fb->bpp, fb->pitch, bo, NULL); nouveau_bo_ref(NULL, &bo); drmFree(fb); if (!pspix) { @@ -236,7 +241,8 @@ drmmode_fbcon_copy(ScreenPtr pScreen) pdpix = drmmode_pixmap_wrap(pScreen, pScrn->virtualX, pScrn->virtualY, pScrn->depth, pScrn->bitsPerPixel, pScrn->displayWidth * - pScrn->bitsPerPixel / 8, pNv->scanout); + pScrn->bitsPerPixel / 8, pNv->scanout, + NULL); if (!pdpix) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Failed to init scanout pixmap for fbcon mirror\n"); @@ -418,7 +424,7 @@ drmmode_crtc_shadow_allocate(xf86CrtcPtr crtc, int width, int height) int ah = height, ret, pitch; void *virtual; - if (pNv->Architecture >= NV_ARCH_50) { + if (pNv->Architecture >= NV_ARCH_50 && pNv->tiled_scanout) { tile_mode = 4; tile_flags = (drmmode->cpp == 2) ? 0x7000 : 0x7a00; ah = NOUVEAU_ALIGN(height, 1 << (tile_mode + 2)); @@ -476,7 +482,7 @@ drmmode_crtc_shadow_create(xf86CrtcPtr crtc, void *data, int width, int height) rotate_pixmap = drmmode_pixmap_wrap(pScrn->pScreen, width, height, pScrn->depth, pScrn->bitsPerPixel, drmmode_crtc->rotate_pitch, - drmmode_crtc->rotate_bo); + drmmode_crtc->rotate_bo, data); drmmode_crtc->rotate_pixmap = rotate_pixmap; return drmmode_crtc->rotate_pixmap; @@ -487,6 +493,7 @@ drmmode_crtc_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap, void *dat { drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; drmmode_ptr drmmode = drmmode_crtc->drmmode; + NVPtr pNv = NVPTR(crtc->scrn); if (rotate_pixmap) FreeScratchPixmapHeader(rotate_pixmap); @@ -494,7 +501,8 @@ drmmode_crtc_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap, void *dat if (data) { drmModeRmFB(drmmode->fd, drmmode_crtc->rotate_fb_id); drmmode_crtc->rotate_fb_id = 0; - nouveau_bo_ref(NULL, &drmmode_crtc->rotate_bo); + if (!pNv->NoAccel) + nouveau_bo_ref(NULL, &drmmode_crtc->rotate_bo); drmmode_crtc->rotate_pixmap = NULL; } } diff --git a/src/nouveau_dri2.c b/src/nouveau_dri2.c index 2666506..a0e89cf 100644 --- a/src/nouveau_dri2.c +++ b/src/nouveau_dri2.c @@ -92,7 +92,6 @@ nouveau_dri2_copy_region(DrawablePtr pDraw, RegionPtr pRegion, struct nouveau_dri2_buffer *dst = nouveau_dri2_buffer(pDstBuffer); PixmapPtr pspix = src->ppix, pdpix = dst->ppix; ScreenPtr pScreen = pDraw->pScreen; - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; RegionPtr pCopyClip; GCPtr pGC; diff --git a/src/nv_driver.c b/src/nv_driver.c index bd061ed..8fd1fa4 100644 --- a/src/nv_driver.c +++ b/src/nv_driver.c @@ -425,7 +425,8 @@ NVCloseScreen(int scrnIndex, ScreenPtr pScreen) drmmode_uevent_fini(pScrn); - nouveau_dri2_fini(pScreen); + if (!pNv->NoAccel) + nouveau_dri2_fini(pScreen); if (pScrn->vtSema) { NVLeaveVT(scrnIndex, 0); -- cgit v1.2.1 From f1ac413d1d3dec2ccf63d4a8c79b9bd9ea578dcf Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Mon, 20 Sep 2010 08:05:00 +1000 Subject: nv50: use 0x8697 on NVAF Signed-off-by: Ben Skeggs --- src/nouveau_class.h | 2 ++ src/nv50_accel.c | 3 +++ 2 files changed, 5 insertions(+) diff --git a/src/nouveau_class.h b/src/nouveau_class.h index c03e633..5ce978a 100644 --- a/src/nouveau_class.h +++ b/src/nouveau_class.h @@ -8970,6 +8970,8 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define NVA8TCL 0x00008597 +#define NVAFTCL 0x00008697 + #define NV50_COMPUTE 0x000050c0 diff --git a/src/nv50_accel.c b/src/nv50_accel.c index bbcea23..f5d2bc3 100644 --- a/src/nv50_accel.c +++ b/src/nv50_accel.c @@ -47,6 +47,9 @@ NVAccelInitNV50TCL(ScrnInfoPtr pScrn) case 0xac: class = NVA0TCL; break; + case 0xaf: + class = NVAFTCL; + break; default: class = NVA8TCL; break; -- cgit v1.2.1 From d5a6f103113985c50bbe749ed341de34af1b47a5 Mon Sep 17 00:00:00 2001 From: Francisco Jerez Date: Tue, 28 Sep 2010 21:49:48 +0200 Subject: dri2: Throttle frontbuffer flushes. There was no need for throttling until the hardware interchannel sync kernel changes because the pushbuf IOCTL blocked to sync the GL and X channels anyway. Signed-off-by: Francisco Jerez --- src/nouveau_dri2.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/nouveau_dri2.c b/src/nouveau_dri2.c index a0e89cf..1387a56 100644 --- a/src/nouveau_dri2.c +++ b/src/nouveau_dri2.c @@ -106,6 +106,13 @@ nouveau_dri2_copy_region(DrawablePtr pDraw, RegionPtr pRegion, pGC->funcs->ChangeClip(pGC, CT_REGION, pCopyClip, 0); ValidateGC(&pdpix->drawable, pGC); + /* Throttle on the previous frame before blitting this one */ + if (dst->base.attachment == DRI2BufferFrontLeft) { + struct nouveau_bo *bo = nouveau_pixmap_bo(dst->ppix); + nouveau_bo_map(bo, NOUVEAU_BO_RD); + nouveau_bo_unmap(bo); + } + pGC->ops->CopyArea(&pspix->drawable, &pdpix->drawable, pGC, 0, 0, pDraw->width, pDraw->height, 0, 0); -- cgit v1.2.1 From 9a5142fae6e1a0a470352f511427916e6fa01b9c Mon Sep 17 00:00:00 2001 From: Maarten Maathuis Date: Fri, 27 Aug 2010 21:11:59 +0200 Subject: nv50/exa: Stop using wfb by default, but add an option to enable it. - Some scenarios, such as those heavy in core font rendering might prefer wfb. - Other (modern) situations are better of with wfb disabled. Signed-off-by: Maarten Maathuis --- man/nouveau.man | 3 +++ src/drmmode_display.c | 2 +- src/nouveau_exa.c | 3 +++ src/nv_const.h | 2 ++ src/nv_driver.c | 5 ++++- 5 files changed, 13 insertions(+), 2 deletions(-) diff --git a/man/nouveau.man b/man/nouveau.man index cd66e9a..0e4c3a2 100644 --- a/man/nouveau.man +++ b/man/nouveau.man @@ -72,6 +72,9 @@ Disable or enable acceleration. Default: acceleration is enabled. .TP .BI "Option \*qShadowFB\*q \*q" boolean \*q Enable or disable use of the shadow framebuffer layer. Default: off. +.TP +.BI "Option \*qWrappedFB\*q \*q" boolean \*q +Enable or disable wfb, only affects nv50+. Useful for some legacy configurations where high rendering latency is perceived. Default: wfb is disabled. .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 011f4dd..08c71c0 100644 --- a/src/drmmode_display.c +++ b/src/drmmode_display.c @@ -1024,7 +1024,7 @@ drmmode_xf86crtc_resize(ScrnInfoPtr scrn, int width, int height) if (scrn->virtualX == width && scrn->virtualY == height) return TRUE; - if (pNv->Architecture >= NV_ARCH_50 && pNv->wfb_enabled) { + if (pNv->Architecture >= NV_ARCH_50 && pNv->tiled_scanout) { tile_mode = 4; tile_flags = (scrn->bitsPerPixel == 16) ? 0x7000 : 0x7a00; ah = NOUVEAU_ALIGN(height, 1 << (tile_mode + 2)); diff --git a/src/nouveau_exa.c b/src/nouveau_exa.c index 3b2c9be..f2995be 100644 --- a/src/nouveau_exa.c +++ b/src/nouveau_exa.c @@ -284,7 +284,10 @@ static Bool nouveau_exa_prepare_access(PixmapPtr ppix, int index) { struct nouveau_bo *bo = nouveau_pixmap_bo(ppix); + NVPtr pNv = NVPTR(xf86Screens[ppix->drawable.pScreen->myNum]); + if (nv50_style_tiled_pixmap(ppix) && !pNv->wfb_enabled) + return FALSE; if (nouveau_bo_map(bo, NOUVEAU_BO_RDWR)) return FALSE; ppix->devPrivate.ptr = bo->map; diff --git a/src/nv_const.h b/src/nv_const.h index 0df25b6..5e1bc50 100644 --- a/src/nv_const.h +++ b/src/nv_const.h @@ -13,6 +13,7 @@ typedef enum { OPTION_NOACCEL, OPTION_SHADOW_FB, OPTION_VIDEO_KEY, + OPTION_WFB, } NVOpts; @@ -22,6 +23,7 @@ static const OptionInfoRec NVOptions[] = { { OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_SHADOW_FB, "ShadowFB", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_VIDEO_KEY, "VideoKey", OPTV_INTEGER, {0}, FALSE }, + { OPTION_WFB, "WrappedFB", OPTV_BOOLEAN, {0}, FALSE }, { -1, NULL, OPTV_NONE, {0}, FALSE } }; diff --git a/src/nv_driver.c b/src/nv_driver.c index 8fd1fa4..b241ac7 100644 --- a/src/nv_driver.c +++ b/src/nv_driver.c @@ -775,7 +775,10 @@ NVPreInit(ScrnInfoPtr pScrn, int flags) } if (!pNv->NoAccel && pNv->Architecture >= NV_ARCH_50) { - pNv->wfb_enabled = TRUE; + if (xf86ReturnOptValBool(pNv->Options, OPTION_WFB, FALSE)) + pNv->wfb_enabled = TRUE; + else + pNv->wfb_enabled = FALSE; /* Default: use UTS/DFS all the time */ pNv->tiled_scanout = TRUE; } -- cgit v1.2.1 From a47c274f329b3b8bfbdcf155d6d832599d823dc8 Mon Sep 17 00:00:00 2001 From: Francisco Jerez Date: Sun, 10 Oct 2010 04:43:25 +0200 Subject: Fix for the last xserver ABI. Signed-off-by: Francisco Jerez --- src/drmmode_display.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/drmmode_display.c b/src/drmmode_display.c index 08c71c0..aafe0f6 100644 --- a/src/drmmode_display.c +++ b/src/drmmode_display.c @@ -1073,7 +1073,9 @@ drmmode_xf86crtc_resize(ScrnInfoPtr scrn, int width, int height) screen->ModifyPixmapHeader(ppix, width, height, -1, -1, pitch, (!pNv->NoAccel || pNv->ShadowPtr) ? pNv->ShadowPtr : pNv->scanout->map); +#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 9 scrn->pixmapPrivate.ptr = ppix->devPrivate.ptr; +#endif nouveau_bo_unmap(pNv->scanout); for (i = 0; i < xf86_config->num_crtc; i++) { -- cgit v1.2.1 From 8c8f15c9d3a31c35bf2ef20faf8c4133295a678f Mon Sep 17 00:00:00 2001 From: Francisco Jerez Date: Sun, 10 Oct 2010 04:36:17 +0200 Subject: nv10-nv40/exa: Fix tiled pixmap pitch alignment calculation. Signed-off-by: Francisco Jerez --- src/nouveau_exa.c | 5 +++-- src/nouveau_local.h | 5 +++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/nouveau_exa.c b/src/nouveau_exa.c index f2995be..92dc946 100644 --- a/src/nouveau_exa.c +++ b/src/nouveau_exa.c @@ -347,8 +347,9 @@ nouveau_exa_create_pixmap(ScreenPtr pScreen, int width, int height, int depth, height = NOUVEAU_ALIGN(height, 1 << (tile_mode + 2)); } else { if (usage_hint & NOUVEAU_CREATE_PIXMAP_TILED) { - int pitch_align = - pNv->dev->chipset >= 0x40 ? 1024 : 256; + int pitch_align = max( + pNv->dev->chipset >= 0x40 ? 1024 : 256, + round_down_pow2(*new_pitch / 4)); *new_pitch = NOUVEAU_ALIGN(*new_pitch, pitch_align); diff --git a/src/nouveau_local.h b/src/nouveau_local.h index a950db4..5d3200a 100644 --- a/src/nouveau_local.h +++ b/src/nouveau_local.h @@ -69,4 +69,9 @@ static inline int log2i(int i) return r; } +static inline int round_down_pow2(int x) +{ + return 1 << log2i(x); +} + #endif -- cgit v1.2.1 From 4f42708c26fa57bac7854701a6e757958c8d0654 Mon Sep 17 00:00:00 2001 From: Francisco Jerez Date: Sun, 10 Oct 2010 04:39:27 +0200 Subject: Update to the last libdrm API. Signed-off-by: Francisco Jerez --- src/drmmode_display.c | 10 +++++----- src/nouveau_exa.c | 11 ++++++++++- src/nouveau_wfb.c | 2 +- src/nv_dma.c | 3 ++- src/nv_driver.c | 4 ++-- 5 files changed, 20 insertions(+), 10 deletions(-) diff --git a/src/drmmode_display.c b/src/drmmode_display.c index aafe0f6..0f82543 100644 --- a/src/drmmode_display.c +++ b/src/drmmode_display.c @@ -420,13 +420,13 @@ drmmode_crtc_shadow_allocate(xf86CrtcPtr crtc, int width, int height) drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; drmmode_ptr drmmode = drmmode_crtc->drmmode; NVPtr pNv = NVPTR(crtc->scrn); - uint32_t tile_mode = 0, tile_flags = 0; + uint32_t tile_mode = 0, tile_flags = NOUVEAU_BO_TILE_SCANOUT; int ah = height, ret, pitch; void *virtual; if (pNv->Architecture >= NV_ARCH_50 && pNv->tiled_scanout) { tile_mode = 4; - tile_flags = (drmmode->cpp == 2) ? 0x7000 : 0x7a00; + tile_flags |= (drmmode->cpp == 2) ? 0x7000 : 0x7a00; ah = NOUVEAU_ALIGN(height, 1 << (tile_mode + 2)); pitch = NOUVEAU_ALIGN(width * drmmode->cpp, 64); } else { @@ -1015,9 +1015,9 @@ drmmode_xf86crtc_resize(ScrnInfoPtr scrn, int width, int height) drmmode_ptr drmmode = drmmode_crtc->drmmode; uint32_t pitch, old_width, old_height, old_pitch, old_fb_id; struct nouveau_bo *old_bo = NULL; - uint32_t tile_mode = 0, tile_flags = 0, ah = height; + uint32_t tile_mode = 0, tile_flags = NOUVEAU_BO_TILE_SCANOUT; PixmapPtr ppix; - int ret, i; + int ret, i, ah = height; ErrorF("resize called %d %d\n", width, height); @@ -1026,7 +1026,7 @@ drmmode_xf86crtc_resize(ScrnInfoPtr scrn, int width, int height) if (pNv->Architecture >= NV_ARCH_50 && pNv->tiled_scanout) { tile_mode = 4; - tile_flags = (scrn->bitsPerPixel == 16) ? 0x7000 : 0x7a00; + tile_flags |= (scrn->bitsPerPixel == 16) ? 0x7000 : 0x7a00; ah = NOUVEAU_ALIGN(height, 1 << (tile_mode + 2)); pitch = NOUVEAU_ALIGN(width * (scrn->bitsPerPixel >> 3), 64); } else { diff --git a/src/nouveau_exa.c b/src/nouveau_exa.c index 92dc946..f3a2abd 100644 --- a/src/nouveau_exa.c +++ b/src/nouveau_exa.c @@ -354,6 +354,14 @@ nouveau_exa_create_pixmap(ScreenPtr pScreen, int width, int height, int depth, *new_pitch = NOUVEAU_ALIGN(*new_pitch, pitch_align); tile_mode = *new_pitch; + + if (bitsPerPixel == 32) + tile_flags |= NOUVEAU_BO_TILE_32BPP; + else if (bitsPerPixel == 16) + tile_flags |= NOUVEAU_BO_TILE_16BPP; + + if (usage_hint & NOUVEAU_CREATE_PIXMAP_ZETA) + tile_flags |= NOUVEAU_BO_TILE_ZETA; } } } else { @@ -392,7 +400,8 @@ nv50_style_tiled_pixmap(PixmapPtr ppix) NVPtr pNv = NVPTR(pScrn); return pNv->Architecture == NV_ARCH_50 && - nouveau_pixmap_bo(ppix)->tile_flags; + (nouveau_pixmap_bo(ppix)->tile_flags & + NOUVEAU_BO_TILE_LAYOUT_MASK); } static Bool diff --git a/src/nouveau_wfb.c b/src/nouveau_wfb.c index 7575672..2425e31 100644 --- a/src/nouveau_wfb.c +++ b/src/nouveau_wfb.c @@ -171,7 +171,7 @@ nouveau_wfb_setup_wrap(ReadMemoryProcPtr *pRead, WriteMemoryProcPtr *pWrite, wfb->ppix = ppix; wfb->base = (unsigned long)ppix->devPrivate.ptr; wfb->end = wfb->base + bo->size; - if (!bo->tile_flags) { + if (!nv50_style_tiled_pixmap(ppix)) { wfb->pitch = 0; } else { wfb->pitch = ppix->devKind; diff --git a/src/nv_dma.c b/src/nv_dma.c index c3d7639..409f42c 100644 --- a/src/nv_dma.c +++ b/src/nv_dma.c @@ -72,7 +72,8 @@ NVInitDma(ScrnInfoPtr pScrn) NVPtr pNv = NVPTR(pScrn); int ret; - ret = nouveau_channel_alloc(pNv->dev, NvDmaFB, NvDmaTT, &pNv->chan); + ret = nouveau_channel_alloc(pNv->dev, NvDmaFB, NvDmaTT, 24*1024, + &pNv->chan); if (ret) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Error creating GPU channel: %d\n", ret); diff --git a/src/nv_driver.c b/src/nv_driver.c index b241ac7..094067d 100644 --- a/src/nv_driver.c +++ b/src/nv_driver.c @@ -856,13 +856,13 @@ NVMapMem(ScrnInfoPtr pScrn) { NVPtr pNv = NVPTR(pScrn); struct nouveau_device *dev = pNv->dev; - uint32_t tile_mode = 0, tile_flags = 0; + uint32_t tile_mode = 0, tile_flags = NOUVEAU_BO_TILE_SCANOUT; int ret, size; size = pScrn->displayWidth * (pScrn->bitsPerPixel >> 3); if (pNv->Architecture >= NV_ARCH_50 && pNv->tiled_scanout) { tile_mode = 4; - tile_flags = pScrn->bitsPerPixel == 16 ? 0x7000 : 0x7a00; + tile_flags |= pScrn->bitsPerPixel == 16 ? 0x7000 : 0x7a00; size *= NOUVEAU_ALIGN(pScrn->virtualY, (1 << (tile_mode + 2))); } else { size *= pScrn->virtualY; -- cgit v1.2.1 From 258e483d47f0f63155be18981c1118261f7675a8 Mon Sep 17 00:00:00 2001 From: Francisco Jerez Date: Thu, 21 Oct 2010 22:41:24 +0200 Subject: kms: Register a wakeup handler to poll vblank/pageflip/udev events. Signed-off-by: Francisco Jerez --- src/drmmode_display.c | 79 ++++++++++++++++++++++++++++++++++++++------------- src/nv_driver.c | 5 ++-- src/nv_proto.h | 4 +-- 3 files changed, 65 insertions(+), 23 deletions(-) diff --git a/src/drmmode_display.c b/src/drmmode_display.c index 0f82543..6c0e910 100644 --- a/src/drmmode_display.c +++ b/src/drmmode_display.c @@ -47,9 +47,9 @@ typedef struct { uint32_t fb_id; drmModeResPtr mode_res; int cpp; + drmEventContext event_context; #ifdef HAVE_LIBUDEV struct udev_monitor *uevent_monitor; - InputHandlerProc uevent_handler; #endif } drmmode_rec, *drmmode_ptr; @@ -85,6 +85,19 @@ typedef struct { static void drmmode_output_dpms(xf86OutputPtr output, int mode); +static drmmode_ptr +drmmode_from_scrn(ScrnInfoPtr scrn) +{ + if (scrn) { + xf86CrtcConfigPtr conf = XF86_CRTC_CONFIG_PTR(scrn); + drmmode_crtc_private_ptr crtc = conf->crtc[0]->driver_private; + + return crtc->drmmode; + } + + return NULL; +} + static PixmapPtr drmmode_pixmap_wrap(ScreenPtr pScreen, int width, int height, int depth, int bpp, int pitch, struct nouveau_bo *bo, void *data) @@ -1187,20 +1200,11 @@ drmmode_cursor_init(ScreenPtr pScreen) } #ifdef HAVE_LIBUDEV -static drmmode_ptr -drmmode_from_scrn(ScrnInfoPtr scrn) -{ - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); - drmmode_crtc_private_ptr drmmode_crtc; - drmmode_crtc = xf86_config->crtc[0]->driver_private; - return drmmode_crtc->drmmode; -} static void -drmmode_handle_uevents(int fd, void *closure) +drmmode_handle_uevents(ScrnInfoPtr scrn) { - ScrnInfoPtr scrn = closure; drmmode_ptr drmmode = drmmode_from_scrn(scrn); struct udev_device *dev; @@ -1213,7 +1217,7 @@ drmmode_handle_uevents(int fd, void *closure) } #endif -void +static void drmmode_uevent_init(ScrnInfoPtr scrn) { #ifdef HAVE_LIBUDEV @@ -1239,26 +1243,63 @@ drmmode_uevent_init(ScrnInfoPtr scrn) return; } - drmmode->uevent_handler = - xf86AddGeneralHandler(udev_monitor_get_fd(mon), - drmmode_handle_uevents, scrn); - + AddGeneralSocket(udev_monitor_get_fd(mon)); drmmode->uevent_monitor = mon; #endif } -void +static void drmmode_uevent_fini(ScrnInfoPtr scrn) { #ifdef HAVE_LIBUDEV drmmode_ptr drmmode = drmmode_from_scrn(scrn); - if (drmmode->uevent_handler) { + if (drmmode->uevent_monitor) { struct udev *u = udev_monitor_get_udev(drmmode->uevent_monitor); - xf86RemoveGeneralHandler(drmmode->uevent_handler); udev_monitor_unref(drmmode->uevent_monitor); udev_unref(u); } #endif } + +static void +drmmode_wakeup_handler(pointer data, int err, pointer p) +{ + ScrnInfoPtr scrn = data; + drmmode_ptr drmmode = drmmode_from_scrn(scrn); + fd_set *read_mask = p; + + if (scrn == NULL || err < 0) + return; + + if (FD_ISSET(drmmode->fd, read_mask)) + drmHandleEvent(drmmode->fd, &drmmode->event_context); + +#ifdef HAVE_LIBUDEV + if (FD_ISSET(udev_monitor_get_fd(drmmode->uevent_monitor), read_mask)) + drmmode_handle_uevents(scrn); +#endif +} + +void +drmmode_screen_init(ScreenPtr pScreen) +{ + ScrnInfoPtr scrn = xf86Screens[pScreen->myNum]; + drmmode_ptr drmmode = drmmode_from_scrn(scrn); + + drmmode_uevent_init(scrn); + AddGeneralSocket(drmmode->fd); + + /* Register a wakeup handler to get informed on DRM events */ + RegisterBlockAndWakeupHandlers((BlockHandlerProcPtr)NoopDDA, + drmmode_wakeup_handler, scrn); +} + +void +drmmode_screen_fini(ScreenPtr pScreen) +{ + ScrnInfoPtr scrn = xf86Screens[pScreen->myNum]; + + drmmode_uevent_fini(scrn); +} diff --git a/src/nv_driver.c b/src/nv_driver.c index 094067d..cd8c001 100644 --- a/src/nv_driver.c +++ b/src/nv_driver.c @@ -423,7 +423,7 @@ NVCloseScreen(int scrnIndex, ScreenPtr pScreen) ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; NVPtr pNv = NVPTR(pScrn); - drmmode_uevent_fini(pScrn); + drmmode_screen_fini(pScreen); if (!pNv->NoAccel) nouveau_dri2_fini(pScreen); @@ -1193,7 +1193,8 @@ NVScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) if (serverGeneration == 1) xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options); - drmmode_uevent_init(pScrn); + drmmode_screen_init(pScreen); + return TRUE; } diff --git a/src/nv_proto.h b/src/nv_proto.h index d6791ef..7c836b2 100644 --- a/src/nv_proto.h +++ b/src/nv_proto.h @@ -7,8 +7,8 @@ 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); -void drmmode_uevent_init(ScrnInfoPtr); -void drmmode_uevent_fini(ScrnInfoPtr); +void drmmode_screen_init(ScreenPtr pScreen); +void drmmode_screen_fini(ScreenPtr pScreen); /* in nv_accel_common.c */ Bool NVAccelCommonInit(ScrnInfoPtr pScrn); -- cgit v1.2.1 From 21ed642d3f76f286f23cd64ca817038ec94a1bf6 Mon Sep 17 00:00:00 2001 From: Francisco Jerez Date: Wed, 13 Oct 2010 18:22:22 +0200 Subject: Make the sync-to-vblank helpers more consistent. Signed-off-by: Francisco Jerez --- src/nouveau_xv.c | 17 ----------------- src/nv04_xv_blit.c | 12 +++--------- src/nv30_xv_tex.c | 20 +++++--------------- src/nv40_xv_tex.c | 20 +++++--------------- src/nv50_accel.c | 28 ++++++++++++++++++++++++++++ src/nv50_xv.c | 33 ++------------------------------- src/nv_accel_common.c | 26 ++++++++++++++++++++++++++ src/nv_proto.h | 3 ++- 8 files changed, 71 insertions(+), 88 deletions(-) diff --git a/src/nouveau_xv.c b/src/nouveau_xv.c index b531f10..695c620 100644 --- a/src/nouveau_xv.c +++ b/src/nouveau_xv.c @@ -193,23 +193,6 @@ nv_window_belongs_to_crtc(ScrnInfoPtr pScrn, int x, int y, int w, int h) return mask; } -void -NVWaitVSync(ScrnInfoPtr pScrn, int crtc) -{ - NVPtr pNv = NVPTR(pScrn); - struct nouveau_channel *chan = pNv->chan; - struct nouveau_grobj *blit = pNv->NvImageBlit; - - BEGIN_RING(chan, blit, 0x0000012C, 1); - OUT_RING (chan, 0); - BEGIN_RING(chan, blit, 0x00000134, 1); - OUT_RING (chan, crtc); - BEGIN_RING(chan, blit, 0x00000100, 1); - OUT_RING (chan, 0); - BEGIN_RING(chan, blit, 0x00000130, 1); - OUT_RING (chan, 0); -} - /** * NVSetPortDefaults * set attributes of port "pPriv" to compiled-in (except for colorKey) defaults diff --git a/src/nv04_xv_blit.c b/src/nv04_xv_blit.c index 3828fa4..55d82c4 100644 --- a/src/nv04_xv_blit.c +++ b/src/nv04_xv_blit.c @@ -82,7 +82,6 @@ NVPutBlitImage(ScrnInfoPtr pScrn, struct nouveau_bo *src, int src_offset, struct nouveau_grobj *rect = pNv->NvRectangle; struct nouveau_grobj *sifm = pNv->NvScaledImage; struct nouveau_bo *bo = nouveau_pixmap_bo(ppix); - unsigned int crtcs; int dst_format; if (!NVAccelGetCtxSurf2DFormatFromPixmap(ppix, &dst_format)) @@ -130,14 +129,9 @@ NVPutBlitImage(ScrnInfoPtr pScrn, struct nouveau_bo *src, int src_offset, } if(pPriv->SyncToVBlank) { - crtcs = nv_window_belongs_to_crtc(pScrn, dstBox->x1, dstBox->y1, - dstBox->x2, dstBox->y2); - - FIRE_RING (chan); - if (crtcs & 0x1) - NVWaitVSync(pScrn, 0); - else if (crtcs & 0x2) - NVWaitVSync(pScrn, 1); + FIRE_RING(chan); + NV11SyncToVBlank(ppix, dstBox->x1, dstBox->y1, + dstBox->x2, dstBox->y2); } if (pNv->dev->chipset >= 0x05) { diff --git a/src/nv30_xv_tex.c b/src/nv30_xv_tex.c index f4bc1da..61558e9 100644 --- a/src/nv30_xv_tex.c +++ b/src/nv30_xv_tex.c @@ -258,7 +258,7 @@ NV30PutTextureImage(ScrnInfoPtr pScrn, struct nouveau_bo *src, int src_offset, struct nouveau_channel *chan = pNv->chan; struct nouveau_grobj *rankine = pNv->Nv3D; struct nouveau_bo *bo = nouveau_pixmap_bo(ppix); - Bool redirected = FALSE, bicubic = pPriv->bicubic; + Bool bicubic = pPriv->bicubic; float X1, X2, Y1, Y2; BoxPtr pbox; int nbox; @@ -275,11 +275,6 @@ NV30PutTextureImage(ScrnInfoPtr pScrn, struct nouveau_bo *src, int src_offset, return BadImplementation; } -#ifdef COMPOSITE - if (!nouveau_exa_pixmap_is_onscreen(ppix)) - redirected = TRUE; -#endif - pbox = REGION_RECTS(clipBoxes); nbox = REGION_NUM_RECTS(clipBoxes); @@ -353,15 +348,10 @@ 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 && !redirected) { - uint8_t crtcs = nv_window_belongs_to_crtc(pScrn, dstBox->x1, dstBox->y1, - dstBox->x2 - dstBox->x1, dstBox->y2 - dstBox->y1); - - FIRE_RING (chan); - if (crtcs & 0x1) - NVWaitVSync(pScrn, 0); - else if (crtcs & 0x2) - NVWaitVSync(pScrn, 1); + if (pPriv->SyncToVBlank) { + FIRE_RING(chan); + NV11SyncToVBlank(ppix, dstBox->x1, dstBox->y1, + dstBox->x2, dstBox->y2); } /* 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 a46f1e3..602bb7a 100644 --- a/src/nv40_xv_tex.c +++ b/src/nv40_xv_tex.c @@ -262,7 +262,7 @@ NV40PutTextureImage(ScrnInfoPtr pScrn, struct nouveau_channel *chan = pNv->chan; struct nouveau_grobj *curie = pNv->Nv3D; struct nouveau_bo *bo = nouveau_pixmap_bo(ppix); - Bool redirected = FALSE, bicubic = pPriv->bicubic; + Bool bicubic = pPriv->bicubic; float X1, X2, Y1, Y2; BoxPtr pbox; int nbox; @@ -279,11 +279,6 @@ NV40PutTextureImage(ScrnInfoPtr pScrn, return BadImplementation; } -#ifdef COMPOSITE - if (!nouveau_exa_pixmap_is_onscreen(ppix)) - redirected = TRUE; -#endif - pbox = REGION_RECTS(clipBoxes); nbox = REGION_NUM_RECTS(clipBoxes); @@ -342,15 +337,10 @@ NV40PutTextureImage(ScrnInfoPtr pScrn, OUT_RING (chan, 1); /* Just before rendering we wait for vblank in the non-composited case. */ - if (pPriv->SyncToVBlank && !redirected) { - uint8_t crtcs = nv_window_belongs_to_crtc(pScrn, dstBox->x1, dstBox->y1, - dstBox->x2 - dstBox->x1, dstBox->y2 - dstBox->y1); - - FIRE_RING (chan); - if (crtcs & 0x1) - NVWaitVSync(pScrn, 0); - else if (crtcs & 0x2) - NVWaitVSync(pScrn, 1); + if (pPriv->SyncToVBlank) { + FIRE_RING(chan); + NV11SyncToVBlank(ppix, dstBox->x1, dstBox->y1, + dstBox->x2, dstBox->y2); } /* These are fixed point values in the 16.16 format. */ diff --git a/src/nv50_accel.c b/src/nv50_accel.c index f5d2bc3..d0def57 100644 --- a/src/nv50_accel.c +++ b/src/nv50_accel.c @@ -23,6 +23,34 @@ #include "nv_include.h" #include "nv50_accel.h" +void +NV50SyncToVBlank(PixmapPtr ppix, int x1, int y1, int x2, int y2) +{ + ScrnInfoPtr pScrn = xf86Screens[ppix->drawable.pScreen->myNum]; + NVPtr pNv = NVPTR(pScrn); + struct nouveau_channel *chan = pNv->chan; + struct nouveau_grobj *nvsw = pNv->NvSW; + int crtcs; + + if (!nouveau_exa_pixmap_is_onscreen(ppix)) + return; + + crtcs = nv_window_belongs_to_crtc(pScrn, x1, y1, x2 - x1, y2 - y1); + if (!crtcs) + return; + + BEGIN_RING(chan, nvsw, 0x0060, 2); + OUT_RING (chan, pNv->vblank_sem->handle); + OUT_RING (chan, 0); + BEGIN_RING(chan, nvsw, 0x006c, 1); + OUT_RING (chan, 0x22222222); + BEGIN_RING(chan, nvsw, 0x0404, 2); + OUT_RING (chan, 0x11111111); + OUT_RING (chan, ffs(crtcs) - 1); + BEGIN_RING(chan, nvsw, 0x0068, 1); + OUT_RING (chan, 0x11111111); +} + Bool NVAccelInitNV50TCL(ScrnInfoPtr pScrn) { diff --git a/src/nv50_xv.c b/src/nv50_xv.c index b9349a2..87e22b5 100644 --- a/src/nv50_xv.c +++ b/src/nv50_xv.c @@ -265,34 +265,6 @@ nv50_xv_state_emit(PixmapPtr ppix, int id, struct nouveau_bo *src, return TRUE; } -static void -NV50EmitWaitForVBlank(PixmapPtr ppix, int x, int y, int w, int h) -{ - ScrnInfoPtr pScrn = xf86Screens[ppix->drawable.pScreen->myNum]; - NVPtr pNv = NVPTR(pScrn); - struct nouveau_channel *chan = pNv->chan; - struct nouveau_grobj *nvsw = pNv->NvSW; - int crtcs; - - if (!nouveau_exa_pixmap_is_onscreen(ppix)) - return; - - crtcs = nv_window_belongs_to_crtc(pScrn, x, y, w, h); - if (!crtcs) - return; - - BEGIN_RING(chan, nvsw, 0x0060, 2); - OUT_RING (chan, pNv->vblank_sem->handle); - OUT_RING (chan, 0); - BEGIN_RING(chan, nvsw, 0x006c, 1); - OUT_RING (chan, 0x22222222); - BEGIN_RING(chan, nvsw, 0x0404, 2); - OUT_RING (chan, 0x11111111); - OUT_RING (chan, ffs(crtcs) - 1); - BEGIN_RING(chan, nvsw, 0x0068, 1); - OUT_RING (chan, 0x11111111); -} - int nv50_xv_image_put(ScrnInfoPtr pScrn, struct nouveau_bo *src, int packed_y, int uv, @@ -317,9 +289,8 @@ nv50_xv_image_put(ScrnInfoPtr pScrn, return BadAlloc; if (pPriv->SyncToVBlank) { - NV50EmitWaitForVBlank(ppix, dstBox->x1, dstBox->y1, - dstBox->x2 - dstBox->x1, - dstBox->y2 - dstBox->y1); + NV50SyncToVBlank(ppix, dstBox->x1, dstBox->y1, + dstBox->x2, dstBox->y2); } /* 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 869a6d6..891615c 100644 --- a/src/nv_accel_common.c +++ b/src/nv_accel_common.c @@ -22,6 +22,32 @@ #include "nv_include.h" +void +NV11SyncToVBlank(PixmapPtr ppix, int x1, int y1, int x2, int y2) +{ + ScrnInfoPtr pScrn = xf86Screens[ppix->drawable.pScreen->myNum]; + NVPtr pNv = NVPTR(pScrn); + struct nouveau_channel *chan = pNv->chan; + struct nouveau_grobj *blit = pNv->NvImageBlit; + int crtcs; + + if (!nouveau_exa_pixmap_is_onscreen(ppix)) + return; + + crtcs = nv_window_belongs_to_crtc(pScrn, x1, y1, x2 - x1, y2 - y1); + if (!crtcs) + return; + + BEGIN_RING(chan, blit, 0x0000012C, 1); + OUT_RING (chan, 0); + BEGIN_RING(chan, blit, 0x00000134, 1); + OUT_RING (chan, ffs(crtcs) - 1); + BEGIN_RING(chan, blit, 0x00000100, 1); + OUT_RING (chan, 0); + BEGIN_RING(chan, blit, 0x00000130, 1); + OUT_RING (chan, 0); +} + static Bool NVAccelInitDmaNotifier0(ScrnInfoPtr pScrn) { diff --git a/src/nv_proto.h b/src/nv_proto.h index 7c836b2..50f67f5 100644 --- a/src/nv_proto.h +++ b/src/nv_proto.h @@ -16,6 +16,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); /* in nouveau_dri2.c */ Bool nouveau_dri2_init(ScreenPtr pScreen); @@ -24,7 +25,6 @@ void nouveau_dri2_fini(ScreenPtr pScreen); /* in nouveau_xv.c */ void NVInitVideo(ScreenPtr); void NVTakedownVideo(ScrnInfoPtr); -void NVWaitVSync(ScrnInfoPtr pScrn, int crtc); void NVSetPortDefaults (ScrnInfoPtr pScrn, NVPortPrivPtr pPriv); unsigned int nv_window_belongs_to_crtc(ScrnInfoPtr, int, int, int, int); @@ -125,6 +125,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); Bool NVAccelInitNV50TCL(ScrnInfoPtr pScrn); /* in nv50_exa.c */ -- cgit v1.2.1 From 72dd4899ff036b09e3680ed2e09b3dbae3a7ba71 Mon Sep 17 00:00:00 2001 From: Francisco Jerez Date: Thu, 21 Oct 2010 22:31:45 +0200 Subject: nv04-nv40/exa: Make the copy hook blit downwards for non-overlapping regions. Signed-off-by: Francisco Jerez --- src/nv04_exa.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/src/nv04_exa.c b/src/nv04_exa.c index 19c5fc5..2760d4b 100644 --- a/src/nv04_exa.c +++ b/src/nv04_exa.c @@ -242,6 +242,41 @@ NV04EXACopy(PixmapPtr pDstPixmap, int srcX, int srcY, int dstX, int dstY, NVPtr pNv = NVPTR(pScrn); struct nouveau_channel *chan = pNv->chan; struct nouveau_grobj *blit = pNv->NvImageBlit; + int split_dstY = NOUVEAU_ALIGN(dstY + 1, 64); + int split_height = split_dstY - dstY; + + if ((width * height) >= 200000 && pNv->pspix != pNv->pdpix && + (dstY > srcY || dstX > srcX) && split_height < height) { + /* + * KLUDGE - Split the destination rectangle in an + * upper misaligned half and a lower tile-aligned + * half, then get IMAGE_BLIT to blit the lower piece + * downwards (required for sync-to-vblank if the area + * to be blitted is large enough). The blob does a + * different (not nicer) trick to achieve the same + * effect. + */ + struct nouveau_grobj *surf2d = pNv->NvContextSurfaces; + struct nouveau_bo *dst_bo = nouveau_pixmap_bo(pNv->pdpix); + unsigned dst_pitch = exaGetPixmapPitch(pNv->pdpix); + + if (MARK_RING(chan, 10, 1)) + return; + + BEGIN_RING(chan, blit, NV01_IMAGE_BLIT_POINT_IN, 3); + OUT_RING (chan, (srcY << 16) | srcX); + OUT_RING (chan, (dstY << 16) | dstX); + OUT_RING (chan, (split_height << 16) | width); + + BEGIN_RING(chan, surf2d, + NV04_CONTEXT_SURFACES_2D_OFFSET_DESTIN, 1); + OUT_RELOCl(chan, dst_bo, split_dstY * dst_pitch, + NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); + + srcY += split_height; + height -= split_height; + dstY = 0; + } WAIT_RING (chan, 4); BEGIN_RING(chan, blit, NV01_IMAGE_BLIT_POINT_IN, 3); -- cgit v1.2.1 From 70f0d2c886ceaa965ca4864788f4dd8e8f757a92 Mon Sep 17 00:00:00 2001 From: Francisco Jerez Date: Thu, 21 Oct 2010 22:55:02 +0200 Subject: dri2: Add sync-to-vblank support. Note that you need a recent enough kernel for it to work. Use the "GLXVBlank" option to enable it (it defaults to disabled for now). Signed-off-by: Francisco Jerez --- man/nouveau.man | 5 ++ src/drmmode_display.c | 4 ++ src/nouveau_dri2.c | 183 ++++++++++++++++++++++++++++++++++++++++++++++++-- src/nv_const.h | 4 +- src/nv_driver.c | 10 +++ src/nv_proto.h | 3 + src/nv_type.h | 1 + 7 files changed, 202 insertions(+), 8 deletions(-) diff --git a/man/nouveau.man b/man/nouveau.man index 0e4c3a2..a8961ad 100644 --- a/man/nouveau.man +++ b/man/nouveau.man @@ -75,6 +75,11 @@ Enable or disable use of the shadow framebuffer layer. Default: off. .TP .BI "Option \*qWrappedFB\*q \*q" boolean \*q Enable or disable wfb, only affects nv50+. Useful for some legacy configurations where high rendering latency is perceived. Default: wfb is disabled. +.TP +.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. .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 6c0e910..115398a 100644 --- a/src/drmmode_display.c +++ b/src/drmmode_display.c @@ -1289,6 +1289,10 @@ drmmode_screen_init(ScreenPtr pScreen) drmmode_ptr drmmode = drmmode_from_scrn(scrn); drmmode_uevent_init(scrn); + + /* Plug in a vblank event handler */ + drmmode->event_context.version = DRM_EVENT_CONTEXT_VERSION; + drmmode->event_context.vblank_handler = nouveau_dri2_vblank_handler; AddGeneralSocket(drmmode->fd); /* Register a wakeup handler to get informed on DRM events */ diff --git a/src/nouveau_dri2.c b/src/nouveau_dri2.c index 1387a56..edb950f 100644 --- a/src/nouveau_dri2.c +++ b/src/nouveau_dri2.c @@ -106,19 +106,187 @@ nouveau_dri2_copy_region(DrawablePtr pDraw, RegionPtr pRegion, pGC->funcs->ChangeClip(pGC, CT_REGION, pCopyClip, 0); ValidateGC(&pdpix->drawable, pGC); - /* Throttle on the previous frame before blitting this one */ - if (dst->base.attachment == DRI2BufferFrontLeft) { - struct nouveau_bo *bo = nouveau_pixmap_bo(dst->ppix); - nouveau_bo_map(bo, NOUVEAU_BO_RD); - nouveau_bo_unmap(bo); - } - pGC->ops->CopyArea(&pspix->drawable, &pdpix->drawable, pGC, 0, 0, pDraw->width, pDraw->height, 0, 0); FreeScratchGC(pGC); } +struct nouveau_dri2_vblank_state { + enum { + SWAP + } action; + + ClientPtr client; + XID draw; + + DRI2BufferPtr dst; + DRI2BufferPtr src; + DRI2SwapEventPtr func; + void *data; +}; + +static Bool +can_sync_to_vblank(DrawablePtr draw) +{ + ScrnInfoPtr scrn = xf86Screens[draw->pScreen->myNum]; + NVPtr pNv = NVPTR(scrn); + PixmapPtr pix = NVGetDrawablePixmap(draw); + + return pNv->glx_vblank && + nouveau_exa_pixmap_is_onscreen(pix) && + nv_window_belongs_to_crtc(scrn, draw->x, draw->y, + draw->width, draw->height); +} + +static int +nouveau_wait_vblank(DrawablePtr draw, int type, CARD64 msc, + CARD64 *pmsc, CARD64 *pust, void *data) +{ + ScrnInfoPtr scrn = xf86Screens[draw->pScreen->myNum]; + NVPtr pNv = NVPTR(scrn); + int crtcs = nv_window_belongs_to_crtc(scrn, draw->x, draw->y, + draw->width, draw->height); + drmVBlank vbl; + int ret; + + vbl.request.type = type | (crtcs == 2 ? DRM_VBLANK_SECONDARY : 0); + vbl.request.sequence = msc; + vbl.request.signal = (unsigned long)data; + + ret = drmWaitVBlank(nouveau_device(pNv->dev)->fd, &vbl); + if (ret) { + xf86DrvMsg(scrn->scrnIndex, X_WARNING, + "Wait for VBlank failed: %s\n", strerror(errno)); + return ret; + } + + if (pmsc) + *pmsc = vbl.reply.sequence; + if (pust) + *pust = (CARD64)vbl.reply.tval_sec * 1000000 + + vbl.reply.tval_usec; + return 0; +} + +static void +nouveau_dri2_finish_swap(DrawablePtr draw, unsigned int frame, + unsigned int tv_sec, unsigned int tv_usec, + struct nouveau_dri2_vblank_state *s) +{ + ScrnInfoPtr scrn = xf86Screens[draw->pScreen->myNum]; + NVPtr pNv = NVPTR(scrn); + PixmapPtr dst_pix = nouveau_dri2_buffer(s->dst)->ppix; + PixmapPtr src_pix = nouveau_dri2_buffer(s->src)->ppix; + 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; + + /* 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); + else + NV11SyncToVBlank(dst_pix, x1, y1, x2, y2); + + FIRE_RING(chan); + } + + + RegionInit(®ion, &box, 0); + nouveau_dri2_copy_region(draw, ®ion, s->dst, s->src); + + DRI2SwapComplete(s->client, draw, frame, tv_sec, tv_usec, + DRI2_BLIT_COMPLETE, s->func, s->data); + free(s); +} + +static Bool +nouveau_dri2_schedule_swap(ClientPtr client, DrawablePtr draw, + DRI2BufferPtr dst, DRI2BufferPtr src, + CARD64 *target_msc, CARD64 divisor, CARD64 remainder, + DRI2SwapEventPtr func, void *data) +{ + struct nouveau_dri2_vblank_state *s; + CARD64 current_msc; + int ret; + + /* Initialize a swap structure */ + s = malloc(sizeof(*s)); + if (!s) + return FALSE; + + *s = (struct nouveau_dri2_vblank_state) + { SWAP, client, draw->id, dst, src, func, data }; + + if (can_sync_to_vblank(draw)) { + /* Get current sequence */ + ret = nouveau_wait_vblank(draw, DRM_VBLANK_RELATIVE, 0, + ¤t_msc, NULL, NULL); + if (ret) + goto fail; + + /* Calculate a swap 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 one frame before the target */ + ret = nouveau_wait_vblank(draw, DRM_VBLANK_ABSOLUTE | + DRM_VBLANK_EVENT, + max(current_msc, *target_msc - 1), + NULL, NULL, s); + if (ret) + goto fail; + + } else { + /* We can't/don't want to sync to vblank, just swap. */ + nouveau_dri2_finish_swap(draw, 0, 0, 0, s); + } + + return TRUE; + +fail: + free(s); + return FALSE; +} + +void +nouveau_dri2_vblank_handler(int fd, unsigned int frame, + unsigned int tv_sec, unsigned int tv_usec, + void *event_data) +{ + struct nouveau_dri2_vblank_state *s = event_data; + DrawablePtr draw; + int ret; + + ret = dixLookupDrawable(&draw, s->draw, serverClient, + M_ANY, DixWriteAccess); + if (ret) + return; + + switch (s->action) { + case SWAP: + nouveau_dri2_finish_swap(draw, frame, tv_sec, tv_usec, s); + break; + } +} + Bool nouveau_dri2_init(ScreenPtr pScreen) { @@ -138,6 +306,7 @@ nouveau_dri2_init(ScreenPtr pScreen) dri2.CreateBuffer = nouveau_dri2_create_buffer; dri2.DestroyBuffer = nouveau_dri2_destroy_buffer; dri2.CopyRegion = nouveau_dri2_copy_region; + dri2.ScheduleSwap = nouveau_dri2_schedule_swap; return DRI2ScreenInit(pScreen, &dri2); } diff --git a/src/nv_const.h b/src/nv_const.h index 5e1bc50..c355cad 100644 --- a/src/nv_const.h +++ b/src/nv_const.h @@ -14,6 +14,7 @@ typedef enum { OPTION_SHADOW_FB, OPTION_VIDEO_KEY, OPTION_WFB, + OPTION_GLX_VBLANK, } NVOpts; @@ -23,7 +24,8 @@ static const OptionInfoRec NVOptions[] = { { OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_SHADOW_FB, "ShadowFB", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_VIDEO_KEY, "VideoKey", OPTV_INTEGER, {0}, FALSE }, - { OPTION_WFB, "WrappedFB", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_WFB, "WrappedFB", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_GLX_VBLANK, "GLXVBlank", OPTV_BOOLEAN, {0}, FALSE }, { -1, NULL, OPTV_NONE, {0}, FALSE } }; diff --git a/src/nv_driver.c b/src/nv_driver.c index cd8c001..e07ce8c 100644 --- a/src/nv_driver.c +++ b/src/nv_driver.c @@ -782,6 +782,16 @@ NVPreInit(ScrnInfoPtr pScrn, int flags) pNv->tiled_scanout = TRUE; } + if (!pNv->NoAccel && pNv->dev->chipset >= 0x11) { + from = X_DEFAULT; + if (xf86GetOptValBool(pNv->Options, OPTION_GLX_VBLANK, + &pNv->glx_vblank)) + from = X_CONFIG; + + xf86DrvMsg(pScrn->scrnIndex, from, "GLX sync to VBlank %s.\n", + pNv->glx_vblank ? "enabled" : "disabled"); + } + 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 50f67f5..89411b2 100644 --- a/src/nv_proto.h +++ b/src/nv_proto.h @@ -19,6 +19,9 @@ void NVAccelFree(ScrnInfoPtr pScrn); void NV11SyncToVBlank(PixmapPtr ppix, int x1, int y1, int x2, int y2); /* in nouveau_dri2.c */ +void nouveau_dri2_vblank_handler(int fd, unsigned int frame, + unsigned int tv_sec, unsigned int tv_usec, + void *event_data); Bool nouveau_dri2_init(ScreenPtr pScreen); void nouveau_dri2_fini(ScreenPtr pScreen); diff --git a/src/nv_type.h b/src/nv_type.h index 9c22ea9..8290b09 100644 --- a/src/nv_type.h +++ b/src/nv_type.h @@ -50,6 +50,7 @@ typedef struct _NVRec { Bool exa_force_cp; Bool wfb_enabled; Bool tiled_scanout; + Bool glx_vblank; ScreenBlockHandlerProcPtr BlockHandler; CreateScreenResourcesProcPtr CreateScreenResources; CloseScreenProcPtr CloseScreen; -- cgit v1.2.1 From 75daada678d03d2e162f8003a6f2edcbe0525f92 Mon Sep 17 00:00:00 2001 From: Francisco Jerez Date: Thu, 14 Oct 2010 22:32:54 +0200 Subject: Restructure tiled pixmap allocation in a single place. Signed-off-by: Francisco Jerez --- src/drmmode_display.c | 56 ++++++++++++++---------------------------- src/nouveau_exa.c | 55 +++++------------------------------------- src/nv_accel_common.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/nv_driver.c | 34 ++++++-------------------- src/nv_proto.h | 3 +++ src/nv_type.h | 5 ++-- 6 files changed, 104 insertions(+), 116 deletions(-) diff --git a/src/drmmode_display.c b/src/drmmode_display.c index 115398a..4220cf5 100644 --- a/src/drmmode_display.c +++ b/src/drmmode_display.c @@ -58,7 +58,7 @@ typedef struct { drmModeCrtcPtr mode_crtc; struct nouveau_bo *cursor; struct nouveau_bo *rotate_bo; - uint32_t rotate_pitch; + int rotate_pitch; PixmapPtr rotate_pixmap; uint32_t rotate_fb_id; Bool cursor_visible; @@ -430,28 +430,18 @@ drmmode_show_cursor (xf86CrtcPtr crtc) static void * drmmode_crtc_shadow_allocate(xf86CrtcPtr crtc, int width, int height) { + ScrnInfoPtr scrn = crtc->scrn; drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; drmmode_ptr drmmode = drmmode_crtc->drmmode; - NVPtr pNv = NVPTR(crtc->scrn); - uint32_t tile_mode = 0, tile_flags = NOUVEAU_BO_TILE_SCANOUT; - int ah = height, ret, pitch; void *virtual; + int ret; - if (pNv->Architecture >= NV_ARCH_50 && pNv->tiled_scanout) { - tile_mode = 4; - tile_flags |= (drmmode->cpp == 2) ? 0x7000 : 0x7a00; - ah = NOUVEAU_ALIGN(height, 1 << (tile_mode + 2)); - pitch = NOUVEAU_ALIGN(width * drmmode->cpp, 64); - } else { - pitch = nv_pitch_align(pNv, width, crtc->scrn->depth); - pitch *= drmmode->cpp; - } - drmmode_crtc->rotate_pitch = pitch; - - ret = nouveau_bo_new_tile(pNv->dev, NOUVEAU_BO_VRAM | NOUVEAU_BO_MAP, 0, - drmmode_crtc->rotate_pitch * ah, tile_mode, - tile_flags, &drmmode_crtc->rotate_bo); - if (ret) { + ret = nouveau_allocate_surface(scrn, width, height, + scrn->bitsPerPixel, + NOUVEAU_CREATE_PIXMAP_SCANOUT, + &drmmode_crtc->rotate_pitch, + &drmmode_crtc->rotate_bo); + if (!ret) { xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR, "Couldn't allocate shadow memory for rotated CRTC\n"); return NULL; @@ -1026,27 +1016,16 @@ drmmode_xf86crtc_resize(ScrnInfoPtr scrn, int width, int height) drmmode_crtc_private_ptr drmmode_crtc = xf86_config->crtc[0]->driver_private; drmmode_ptr drmmode = drmmode_crtc->drmmode; - uint32_t pitch, old_width, old_height, old_pitch, old_fb_id; + uint32_t old_width, old_height, old_pitch, old_fb_id; struct nouveau_bo *old_bo = NULL; - uint32_t tile_mode = 0, tile_flags = NOUVEAU_BO_TILE_SCANOUT; + int ret, i, pitch; PixmapPtr ppix; - int ret, i, ah = height; ErrorF("resize called %d %d\n", width, height); if (scrn->virtualX == width && scrn->virtualY == height) return TRUE; - if (pNv->Architecture >= NV_ARCH_50 && pNv->tiled_scanout) { - tile_mode = 4; - tile_flags |= (scrn->bitsPerPixel == 16) ? 0x7000 : 0x7a00; - ah = NOUVEAU_ALIGN(height, 1 << (tile_mode + 2)); - pitch = NOUVEAU_ALIGN(width * (scrn->bitsPerPixel >> 3), 64); - } else { - pitch = nv_pitch_align(pNv, width, scrn->depth); - pitch *= (scrn->bitsPerPixel >> 3); - } - old_width = scrn->virtualX; old_height = scrn->virtualY; old_pitch = scrn->displayWidth; @@ -1054,16 +1033,17 @@ drmmode_xf86crtc_resize(ScrnInfoPtr scrn, int width, int height) nouveau_bo_ref(pNv->scanout, &old_bo); nouveau_bo_ref(NULL, &pNv->scanout); + ret = nouveau_allocate_surface(scrn, width, height, + scrn->bitsPerPixel, + NOUVEAU_CREATE_PIXMAP_SCANOUT, + &pitch, &pNv->scanout); + if (!ret) + goto fail; + scrn->virtualX = width; scrn->virtualY = height; scrn->displayWidth = pitch / (scrn->bitsPerPixel >> 3); - ret = nouveau_bo_new_tile(pNv->dev, NOUVEAU_BO_VRAM | NOUVEAU_BO_MAP, - 0, pitch * ah, tile_mode, tile_flags, - &pNv->scanout); - if (ret) - goto fail; - nouveau_bo_map(pNv->scanout, NOUVEAU_BO_RDWR); ret = drmModeAddFB(drmmode->fd, width, height, scrn->depth, diff --git a/src/nouveau_exa.c b/src/nouveau_exa.c index f3a2abd..4618994 100644 --- a/src/nouveau_exa.c +++ b/src/nouveau_exa.c @@ -312,10 +312,10 @@ static void * nouveau_exa_create_pixmap(ScreenPtr pScreen, int width, int height, int depth, int usage_hint, int bitsPerPixel, int *new_pitch) { - NVPtr pNv = NVPTR(xf86Screens[pScreen->myNum]); + ScrnInfoPtr scrn = xf86Screens[pScreen->myNum]; + NVPtr pNv = NVPTR(scrn); struct nouveau_pixmap *nvpix; - uint32_t flags = NOUVEAU_BO_MAP, tile_mode = 0, tile_flags = 0; - int ret, size, cpp = bitsPerPixel >> 3; + int ret; if (!width || !height) return calloc(1, sizeof(*nvpix)); @@ -328,52 +328,9 @@ nouveau_exa_create_pixmap(ScreenPtr pScreen, int width, int height, int depth, if (!nvpix) return NULL; - if (cpp) { - flags |= NOUVEAU_BO_VRAM; - *new_pitch = width * cpp; - - if (pNv->Architecture >= NV_ARCH_50) { - if (height > 32) tile_mode = 4; - else if (height > 16) tile_mode = 3; - else if (height > 8) tile_mode = 2; - else if (height > 4) tile_mode = 1; - else tile_mode = 0; - - if (usage_hint & NOUVEAU_CREATE_PIXMAP_ZETA) - tile_flags = 0x2800; - else - tile_flags = 0x7000; - - height = NOUVEAU_ALIGN(height, 1 << (tile_mode + 2)); - } else { - if (usage_hint & NOUVEAU_CREATE_PIXMAP_TILED) { - int pitch_align = max( - pNv->dev->chipset >= 0x40 ? 1024 : 256, - round_down_pow2(*new_pitch / 4)); - - *new_pitch = NOUVEAU_ALIGN(*new_pitch, - pitch_align); - tile_mode = *new_pitch; - - if (bitsPerPixel == 32) - tile_flags |= NOUVEAU_BO_TILE_32BPP; - else if (bitsPerPixel == 16) - tile_flags |= NOUVEAU_BO_TILE_16BPP; - - if (usage_hint & NOUVEAU_CREATE_PIXMAP_ZETA) - tile_flags |= NOUVEAU_BO_TILE_ZETA; - } - } - } else { - *new_pitch = (width * bitsPerPixel + 7) / 8; - } - - *new_pitch = NOUVEAU_ALIGN(*new_pitch, 64); - size = *new_pitch * height; - - ret = nouveau_bo_new_tile(pNv->dev, flags, 0, size, tile_mode, - tile_flags, &nvpix->bo); - if (ret) { + ret = nouveau_allocate_surface(scrn, width, height, bitsPerPixel, + usage_hint, new_pitch, &nvpix->bo); + if (!ret) { free(nvpix); return NULL; } diff --git a/src/nv_accel_common.c b/src/nv_accel_common.c index 891615c..3739c79 100644 --- a/src/nv_accel_common.c +++ b/src/nv_accel_common.c @@ -22,6 +22,73 @@ #include "nv_include.h" +Bool +nouveau_allocate_surface(ScrnInfoPtr scrn, int width, int height, int bpp, + int usage_hint, int *pitch, struct nouveau_bo **bo) +{ + NVPtr pNv = NVPTR(scrn); + Bool scanout = (usage_hint & NOUVEAU_CREATE_PIXMAP_SCANOUT); + Bool tiled = (usage_hint & NOUVEAU_CREATE_PIXMAP_TILED); + int tile_mode = 0, tile_flags = 0; + int flags = NOUVEAU_BO_MAP | (bpp >= 8 ? NOUVEAU_BO_VRAM : 0); + int ret; + + if ((scanout && pNv->tiled_scanout) || + (!scanout && pNv->Architecture >= NV_ARCH_50 && bpp >= 8)) + tiled = TRUE; + + *pitch = NOUVEAU_ALIGN(width * bpp, 512) / 8; + + if (tiled) { + if (pNv->Architecture >= NV_ARCH_50) { + if (height > 32) + tile_mode = 4; + else if (height > 16) + tile_mode = 3; + else if (height > 8) + tile_mode = 2; + else if (height > 4) + tile_mode = 1; + else + tile_mode = 0; + + if (usage_hint & NOUVEAU_CREATE_PIXMAP_ZETA) + tile_flags = 0x2800; + else if (usage_hint & NOUVEAU_CREATE_PIXMAP_SCANOUT) + tile_flags = (bpp == 16 ? 0x7000 : 0x7a00); + else + tile_flags = 0x7000; + + height = NOUVEAU_ALIGN(height, 1 << (tile_mode + 2)); + } else { + int pitch_align = max( + pNv->dev->chipset >= 0x40 ? 1024 : 256, + round_down_pow2(*pitch / 4)); + + tile_mode = *pitch = + NOUVEAU_ALIGN(*pitch, pitch_align); + } + } + + if (bpp == 32) + tile_flags |= NOUVEAU_BO_TILE_32BPP; + else if (bpp == 16) + tile_flags |= NOUVEAU_BO_TILE_16BPP; + + if (usage_hint & NOUVEAU_CREATE_PIXMAP_ZETA) + tile_flags |= NOUVEAU_BO_TILE_ZETA; + + if (usage_hint & NOUVEAU_CREATE_PIXMAP_SCANOUT) + tile_flags |= NOUVEAU_BO_TILE_SCANOUT; + + ret = nouveau_bo_new_tile(pNv->dev, flags, 0, *pitch * height, + tile_mode, tile_flags, bo); + if (ret) + return FALSE; + + return TRUE; +} + void NV11SyncToVBlank(PixmapPtr ppix, int x1, int y1, int x2, int y2) { diff --git a/src/nv_driver.c b/src/nv_driver.c index e07ce8c..e891cf3 100644 --- a/src/nv_driver.c +++ b/src/nv_driver.c @@ -815,16 +815,6 @@ NVPreInit(ScrnInfoPtr pScrn, int flags) if (!xf86SetGamma(pScrn, gammazeros)) NVPreInitFail("\n"); - if (pNv->Architecture >= NV_ARCH_50 && pNv->tiled_scanout) { - int cpp = pScrn->bitsPerPixel >> 3; - pScrn->displayWidth = pScrn->virtualX * cpp; - pScrn->displayWidth = NOUVEAU_ALIGN(pScrn->displayWidth, 64); - pScrn->displayWidth = pScrn->displayWidth / cpp; - } else { - pScrn->displayWidth = nv_pitch_align(pNv, pScrn->virtualX, - pScrn->depth); - } - /* No usable mode */ if (!pScrn->modes) return FALSE; @@ -866,29 +856,19 @@ NVMapMem(ScrnInfoPtr pScrn) { NVPtr pNv = NVPTR(pScrn); struct nouveau_device *dev = pNv->dev; - uint32_t tile_mode = 0, tile_flags = NOUVEAU_BO_TILE_SCANOUT; - int ret, size; - - size = pScrn->displayWidth * (pScrn->bitsPerPixel >> 3); - if (pNv->Architecture >= NV_ARCH_50 && pNv->tiled_scanout) { - tile_mode = 4; - tile_flags |= pScrn->bitsPerPixel == 16 ? 0x7000 : 0x7a00; - size *= NOUVEAU_ALIGN(pScrn->virtualY, (1 << (tile_mode + 2))); - } else { - size *= pScrn->virtualY; - } + int ret, pitch, size; - ret = nouveau_bo_new_tile(dev, NOUVEAU_BO_VRAM | NOUVEAU_BO_MAP, - 0, size, tile_mode, tile_flags, - &pNv->scanout); - if (ret) { + ret = nouveau_allocate_surface(pScrn, pScrn->virtualX, pScrn->virtualY, + pScrn->bitsPerPixel, + NOUVEAU_CREATE_PIXMAP_SCANOUT, + &pitch, &pNv->scanout); + if (!ret) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Error allocating scanout buffer: %d\n", ret); return FALSE; } - nouveau_bo_map(pNv->scanout, NOUVEAU_BO_RDWR); - nouveau_bo_unmap(pNv->scanout); + pScrn->displayWidth = pitch / (pScrn->bitsPerPixel / 8); if (pNv->NoAccel) return TRUE; diff --git a/src/nv_proto.h b/src/nv_proto.h index 89411b2..ba234b3 100644 --- a/src/nv_proto.h +++ b/src/nv_proto.h @@ -17,6 +17,9 @@ 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); +Bool nouveau_allocate_surface(ScrnInfoPtr scrn, int width, int height, + int bpp, int usage_hint, int *pitch, + struct nouveau_bo **bo); /* in nouveau_dri2.c */ void nouveau_dri2_vblank_handler(int fd, unsigned int frame, diff --git a/src/nv_type.h b/src/nv_type.h index 8290b09..a9c693f 100644 --- a/src/nv_type.h +++ b/src/nv_type.h @@ -151,8 +151,9 @@ typedef struct _NVPortPrivRec { #define TIMER_MASK (OFF_TIMER | FREE_TIMER) /* EXA driver-controlled pixmaps */ -#define NOUVEAU_CREATE_PIXMAP_ZETA 0x10000000 -#define NOUVEAU_CREATE_PIXMAP_TILED 0x20000000 +#define NOUVEAU_CREATE_PIXMAP_ZETA 0x10000000 +#define NOUVEAU_CREATE_PIXMAP_TILED 0x20000000 +#define NOUVEAU_CREATE_PIXMAP_SCANOUT 0x40000000 struct nouveau_pixmap { struct nouveau_bo *bo; -- cgit v1.2.1 From 4642d71bdffc04ce0dd458225541940c65f5443d Mon Sep 17 00:00:00 2001 From: Francisco Jerez Date: Thu, 14 Oct 2010 22:17:58 +0200 Subject: dri2: Give out buffers ready for scanout. Signed-off-by: Francisco Jerez --- src/nouveau_dri2.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/nouveau_dri2.c b/src/nouveau_dri2.c index edb950f..66fe16c 100644 --- a/src/nouveau_dri2.c +++ b/src/nouveau_dri2.c @@ -49,6 +49,8 @@ nouveau_dri2_create_buffer(DrawablePtr pDraw, unsigned int attachment, if (attachment == DRI2BufferDepth || attachment == DRI2BufferDepthStencil) usage_hint |= NOUVEAU_CREATE_PIXMAP_ZETA; + else + usage_hint |= NOUVEAU_CREATE_PIXMAP_SCANOUT; ppix = pScreen->CreatePixmap(pScreen, pDraw->width, pDraw->height, pDraw->depth, -- cgit v1.2.1 From c88f13e25b0040c1dd0f93e0ac40f62a6005ce59 Mon Sep 17 00:00:00 2001 From: Francisco Jerez Date: Thu, 14 Oct 2010 22:25:50 +0200 Subject: Allocate a tiled scanout on pre-nv50 too. Pageflip between tiled and non-tiled surfaces isn't such a good idea. Signed-off-by: Francisco Jerez --- src/nv_driver.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/nv_driver.c b/src/nv_driver.c index e891cf3..5ef7984 100644 --- a/src/nv_driver.c +++ b/src/nv_driver.c @@ -774,11 +774,11 @@ NVPreInit(ScrnInfoPtr pScrn, int flags) "Using \"Shadow Framebuffer\" - acceleration disabled\n"); } - if (!pNv->NoAccel && pNv->Architecture >= NV_ARCH_50) { - if (xf86ReturnOptValBool(pNv->Options, OPTION_WFB, FALSE)) - pNv->wfb_enabled = TRUE; - else - pNv->wfb_enabled = FALSE; /* Default: use UTS/DFS all the time */ + if (!pNv->NoAccel) { + if (pNv->Architecture >= NV_ARCH_50) + pNv->wfb_enabled = xf86ReturnOptValBool( + pNv->Options, OPTION_WFB, FALSE); + pNv->tiled_scanout = TRUE; } -- cgit v1.2.1 From eb83c830c87bce345748edef3b50660246143db7 Mon Sep 17 00:00:00 2001 From: Francisco Jerez Date: Thu, 21 Oct 2010 22:57:08 +0200 Subject: dri2: Add pageflip/exchange support. Signed-off-by: Francisco Jerez --- src/drmmode_display.c | 40 ++++++++++++++++++++++++++++++++++++++- src/nouveau_dri2.c | 52 +++++++++++++++++++++++++++++++++++++++++++++------ src/nouveau_local.h | 6 ++++++ src/nv_driver.c | 11 +++++++++++ src/nv_proto.h | 1 + src/nv_type.h | 1 + 6 files changed, 104 insertions(+), 7 deletions(-) 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 @@ -128,6 +128,20 @@ struct nouveau_dri2_vblank_state { void *data; }; +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) { @@ -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; -- cgit v1.2.1 From a685a5c3be12f3e95a6ec1140af115e7ef28fcaa Mon Sep 17 00:00:00 2001 From: Francisco Jerez Date: Wed, 13 Oct 2010 18:45:04 +0200 Subject: dri2: Implement the ScheduleWaitMSC/GetMSC hooks. Signed-off-by: Francisco Jerez --- src/nouveau_dri2.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 69 insertions(+), 1 deletion(-) 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); } -- cgit v1.2.1 From c61e8d03161adcfbba4162172153814accf9e86b Mon Sep 17 00:00:00 2001 From: Francisco Jerez Date: Fri, 22 Oct 2010 23:05:24 +0200 Subject: Make the sync-to-vblank helpers take a box as argument. Signed-off-by: Francisco Jerez --- src/nouveau_dri2.c | 20 ++++++++------------ src/nv04_xv_blit.c | 3 +-- src/nv30_xv_tex.c | 3 +-- src/nv40_xv_tex.c | 3 +-- src/nv50_accel.c | 6 ++++-- src/nv50_xv.c | 3 +-- src/nv_accel_common.c | 6 ++++-- src/nv_proto.h | 4 ++-- 8 files changed, 22 insertions(+), 26 deletions(-) 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 */ -- cgit v1.2.1 From d0f2e16bc35660d01d3cd20a770cf8e613ab5323 Mon Sep 17 00:00:00 2001 From: Francisco Jerez Date: Fri, 22 Oct 2010 23:06:28 +0200 Subject: dri2: Report damage on page-flipped drawables. Signed-off-by: Francisco Jerez --- src/nouveau_dri2.c | 2 ++ 1 file changed, 2 insertions(+) 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); -- cgit v1.2.1 From a4d580bf05d7aac1d486e5d1ba9a2201c026e5f5 Mon Sep 17 00:00:00 2001 From: Francisco Jerez Date: Fri, 22 Oct 2010 23:09:30 +0200 Subject: Bump the required X server version to 1.8. Signed-off-by: Francisco Jerez --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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") -- cgit v1.2.1 From d40c16f5497739c0215f37566db1651a74cb20ba Mon Sep 17 00:00:00 2001 From: Francisco Jerez Date: Sat, 23 Oct 2010 02:20:30 +0200 Subject: dri2: Fix build on X server 1.8. Signed-off-by: Francisco Jerez --- src/nouveau_dri2.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) 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); } -- cgit v1.2.1 From 9737a812aacbc544b93eeaa031cf1c2e8adbd661 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Mon, 25 Oct 2010 10:37:08 +1000 Subject: 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 --- man/nouveau.man | 10 ++++++++ src/drmmode_display.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++---- src/nv_const.h | 2 ++ src/nv_driver.c | 19 +++++++++++++-- src/nv_type.h | 1 + 5 files changed, 92 insertions(+), 6 deletions(-) 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; -- cgit v1.2.1 From 22020457f43eceaf26532ecb50e46d743f4a691f Mon Sep 17 00:00:00 2001 From: Francisco Jerez Date: Tue, 26 Oct 2010 00:24:06 +0200 Subject: dri2: Fix throttling on occluded drawables. Signed-off-by: Francisco Jerez --- src/nouveau_dri2.c | 7 +++++++ 1 file changed, 7 insertions(+) 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); } -- cgit v1.2.1 From 1143e7a97dce1b741376e178b73b8b766e03849a Mon Sep 17 00:00:00 2001 From: Jesse Adkins Date: Tue, 26 Oct 2010 16:05:32 -0700 Subject: Purge cvs tags. Signed-off-by: Jesse Adkins Signed-off-by: Francisco Jerez --- src/nv_const.h | 2 -- src/nv_include.h | 2 -- 2 files changed, 4 deletions(-) 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__ -- cgit v1.2.1 From 4b1d26578116f4d1745dd92a7c99413972a2bedf Mon Sep 17 00:00:00 2001 From: Francisco Jerez Date: Thu, 25 Nov 2010 21:33:46 +0100 Subject: dri2: Don't return failure from schedule_wait if sync-to-vblank is unavailable. Reported-by: Ben Skeggs Signed-off-by: Francisco Jerez --- src/nouveau_dri2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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)); -- cgit v1.2.1 From f29afe65b67c9b89ceba421d9b3aee590f7ded20 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Mon, 29 Nov 2010 09:23:35 +1000 Subject: dri2: don't return failure from get_msc if sync-to-vblank isn't available Signed-off-by: Ben Skeggs --- src/nouveau_dri2.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) 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); -- cgit v1.2.1 From 8bb8231236a6b877895663aeaa9cef731d67fe68 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Tue, 30 Nov 2010 15:27:36 +1000 Subject: dri2: fix certain clients blocking forever when sync-to-vblank unavailable Signed-off-by: Ben Skeggs --- src/nouveau_dri2.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) 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)); -- cgit v1.2.1