summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristoph Bumiller <e0425955@student.tuwien.ac.at>2010-12-09 01:31:40 +0100
committerChristoph Bumiller <e0425955@student.tuwien.ac.at>2010-12-09 01:31:40 +0100
commit178356391ff6831599eba257a5912079894641a1 (patch)
tree34a0d4d1bb0b7d7050abb981a7fdd10313687cb8
parent8573280871401e29f27fa24d0b7c6ac5e35b2cc1 (diff)
parent8bb8231236a6b877895663aeaa9cef731d67fe68 (diff)
downloadxorg-driver-xf86-video-nouveau-178356391ff6831599eba257a5912079894641a1.tar.gz
Merge remote branch 'origin/master' into nvc0
Conflicts: src/drmmode_display.c src/nouveau_exa.c src/nv_driver.c src/nv_type.h
-rw-r--r--configure.ac2
-rw-r--r--man/nouveau.man18
-rw-r--r--src/drmmode_display.c277
-rw-r--r--src/nouveau_class.h2
-rw-r--r--src/nouveau_dri2.c298
-rw-r--r--src/nouveau_exa.c111
-rw-r--r--src/nouveau_local.h11
-rw-r--r--src/nouveau_wfb.c2
-rw-r--r--src/nouveau_xv.c20
-rw-r--r--src/nv04_exa.c39
-rw-r--r--src/nv04_xv_blit.c11
-rw-r--r--src/nv30_xv_tex.c19
-rw-r--r--src/nv40_xv_tex.c19
-rw-r--r--src/nv50_accel.c33
-rw-r--r--src/nv50_xv.c52
-rw-r--r--src/nv_accel_common.c113
-rw-r--r--src/nv_const.h8
-rw-r--r--src/nv_dma.c3
-rw-r--r--src/nv_driver.c123
-rw-r--r--src/nv_include.h2
-rw-r--r--src/nv_proto.h14
-rw-r--r--src/nv_type.h8
22 files changed, 863 insertions, 322 deletions
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")
diff --git a/man/nouveau.man b/man/nouveau.man
index cd66e9a..39de690 100644
--- a/man/nouveau.man
+++ b/man/nouveau.man
@@ -72,6 +72,24 @@ 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.
+.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.
+.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 fb0fa50..c5b57eb 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;
@@ -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;
@@ -85,19 +85,37 @@ 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)
+ 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 +242,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 +254,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");
@@ -411,34 +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 = 0;
- int ah = height, ret, pitch;
void *virtual;
+ int ret;
- if (pNv->Architecture >= NV_ARCH_50) {
- tile_mode = 4;
- if (pNv->Architecture == NV_ARCH_C0) {
- tile_flags = 0xfe0;
- ah = NOUVEAU_ALIGN(height, 1 << (tile_mode + 3));
- } else {
- 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,
- 1 << 17,
- 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;
@@ -482,7 +485,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;
@@ -493,6 +496,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);
@@ -500,7 +504,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;
}
}
@@ -940,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,
@@ -968,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);
@@ -998,8 +1060,6 @@ drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num)
output->interlaceAllowed = true;
output->doubleScanAllowed = true;
-
- return;
}
static Bool
@@ -1011,33 +1071,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 = 0, ah = height;
+ int ret, i, pitch;
PixmapPtr ppix;
- int ret, i;
ErrorF("resize called %d %d\n", width, height);
if (scrn->virtualX == width && scrn->virtualY == height)
return TRUE;
- if (pNv->Architecture >= NV_ARCH_50 && pNv->wfb_enabled) {
- tile_mode = 4;
- if (pNv->Architecture == NV_ARCH_C0) {
- tile_flags = 0xfe0;
- ah = NOUVEAU_ALIGN(height, 1 << (tile_mode + 3));
- } else {
- 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;
@@ -1045,16 +1088,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,
- 1 << 17, 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,
@@ -1077,7 +1121,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++) {
@@ -1130,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);
@@ -1188,21 +1237,50 @@ drmmode_cursor_init(ScreenPtr pScreen)
return xf86_cursors_init(pScreen, size, size, flags);
}
-#ifdef HAVE_LIBUDEV
-static drmmode_ptr
-drmmode_from_scrn(ScrnInfoPtr scrn)
+Bool
+drmmode_page_flip(DrawablePtr draw, PixmapPtr back, void *priv)
{
- xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
- drmmode_crtc_private_ptr drmmode_crtc;
+ 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;
- drmmode_crtc = xf86_config->crtc[0]->driver_private;
- return drmmode_crtc->drmmode;
+ 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(int fd, void *closure)
+drmmode_handle_uevents(ScrnInfoPtr scrn)
{
- ScrnInfoPtr scrn = closure;
drmmode_ptr drmmode = drmmode_from_scrn(scrn);
struct udev_device *dev;
@@ -1215,7 +1293,7 @@ drmmode_handle_uevents(int fd, void *closure)
}
#endif
-void
+static void
drmmode_uevent_init(ScrnInfoPtr scrn)
{
#ifdef HAVE_LIBUDEV
@@ -1241,26 +1319,67 @@ 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);
+
+ /* 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 */
+ 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/nouveau_class.h b/src/nouveau_class.h
index 688158a..e0ef4b9 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/nouveau_dri2.c b/src/nouveau_dri2.c
index f7675fc..2dd6da4 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,
@@ -92,8 +94,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];
- NVPtr pNv = NVPTR(pScrn);
RegionPtr pCopyClip;
GCPtr pGC;
@@ -112,8 +112,297 @@ nouveau_dri2_copy_region(DrawablePtr pDraw, RegionPtr pRegion,
pDraw->width, pDraw->height, 0, 0);
FreeScratchGC(pGC);
+}
+
+struct nouveau_dri2_vblank_state {
+ enum {
+ SWAP,
+ WAIT
+ } action;
+
+ ClientPtr client;
+ XID draw;
+
+ DRI2BufferPtr dst;
+ DRI2BufferPtr src;
+ DRI2SwapEventPtr func;
+ 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)
+{
+ 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;
+ RegionRec reg;
+ int type, ret;
+
+ REGION_INIT(0, &reg, (&(BoxRec){ 0, 0, draw->width, draw->height }), 0);
+ REGION_TRANSLATE(0, &reg, 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)) {
+ /* 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, REGION_EXTENTS(0, &reg));
+ else
+ NV11SyncToVBlank(dst_pix, REGION_EXTENTS(0, &reg));
+
+ FIRE_RING(chan);
+ }
+
+ if (can_exchange(draw, dst_pix, src_pix)) {
+ type = DRI2_EXCHANGE_COMPLETE;
+ DamageRegionAppend(draw, &reg);
+
+ 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);
+
+ 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, &reg, -draw->x, -draw->y);
+ nouveau_dri2_copy_region(draw, &reg, 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,
+ type, s->func, s->data);
+out:
+ free(s);
+}
- FIRE_RING(pNv->chan);
+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,
+ &current_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;
+}
+
+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)) {
+ DRI2WaitMSCComplete(client, draw, target_msc, 0, 0);
+ return TRUE;
+ }
+
+ /* 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,
+ &current_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)) {
+ *ust = 0;
+ *msc = 0;
+ return TRUE;
+ }
+
+ /* 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,
+ 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;
+
+ case WAIT:
+ DRI2WaitMSCComplete(s->client, draw, frame, tv_sec, tv_usec);
+ free(s);
+ break;
+ }
}
Bool
@@ -135,6 +424,9 @@ 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;
+ dri2.ScheduleWaitMSC = nouveau_dri2_schedule_wait;
+ dri2.GetMSC = nouveau_dri2_get_msc;
return DRI2ScreenInit(pScreen, &dri2);
}
diff --git a/src/nouveau_exa.c b/src/nouveau_exa.c
index d07d94a..d900e99 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))
@@ -291,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;
@@ -316,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));
@@ -332,61 +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 (pNv->Architecture >= NV_ARCH_C0) {
- if (tile_mode && height <= 64)
- tile_mode -= 1;
-
- if (usage_hint & NOUVEAU_CREATE_PIXMAP_ZETA)
- tile_flags = 0xdb0;
- else
- tile_flags = 0xfe0;
-
- height = NOUVEAU_ALIGN(
- height, 1 << (tile_mode + 3));
- } else {
- 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 =
- pNv->dev->chipset >= 0x40 ? 1024 : 256;
-
- *new_pitch = NOUVEAU_ALIGN(*new_pitch,
- pitch_align);
- tile_mode = *new_pitch;
- }
- }
- } else {
- *new_pitch = (width * bitsPerPixel + 7) / 8;
- }
-
- *new_pitch = NOUVEAU_ALIGN(*new_pitch, 64);
- size = *new_pitch * height;
-
- xf86DrvMsg(xf86Screens[pScreen->myNum]->scrnIndex, X_INFO,
- "exaCreatePixmap: tile_mode=%x tile_flags=%x size=%x\n",
- tile_mode, tile_flags, size);
-
- 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;
}
@@ -413,7 +357,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
@@ -560,7 +505,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 {
diff --git a/src/nouveau_local.h b/src/nouveau_local.h
index a950db4..38b861f 100644
--- a/src/nouveau_local.h
+++ b/src/nouveau_local.h
@@ -69,4 +69,15 @@ static inline int log2i(int i)
return r;
}
+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/nouveau_wfb.c b/src/nouveau_wfb.c
index 1f62a50..feab54a 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/nouveau_xv.c b/src/nouveau_xv.c
index 4437aa6..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
@@ -1983,7 +1966,8 @@ NV50TexturedImages[] =
{
XVIMAGE_YV12,
XVIMAGE_I420,
- XVIMAGE_YUY2
+ XVIMAGE_YUY2,
+ XVIMAGE_UYVY
};
static XF86VideoAdaptorPtr
diff --git a/src/nv04_exa.c b/src/nv04_exa.c
index c5e44a5..2760d4b 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 */
}
@@ -246,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);
diff --git a/src/nv04_xv_blit.c b/src/nv04_xv_blit.c
index 3828fa4..be39c0d 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,8 @@ 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);
}
if (pNv->dev->chipset >= 0x05) {
diff --git a/src/nv30_xv_tex.c b/src/nv30_xv_tex.c
index f4bc1da..ffa68e4 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,9 @@ 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);
}
/* 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..e0444e8 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,9 @@ 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);
}
/* These are fixed point values in the 16.16 format. */
diff --git a/src/nv50_accel.c b/src/nv50_accel.c
index bbcea23..95d1886 100644
--- a/src/nv50_accel.c
+++ b/src/nv50_accel.c
@@ -23,6 +23,36 @@
#include "nv_include.h"
#include "nv50_accel.h"
+void
+NV50SyncToVBlank(PixmapPtr ppix, BoxPtr box)
+{
+ 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, box->x1, box->y1,
+ box->x2 - box->x1,
+ box->y2 - box->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)
{
@@ -47,6 +77,9 @@ NVAccelInitNV50TCL(ScrnInfoPtr pScrn)
case 0xac:
class = NVA0TCL;
break;
+ case 0xaf:
+ class = NVAFTCL;
+ break;
default:
class = NVA8TCL;
break;
diff --git a/src/nv50_xv.c b/src/nv50_xv.c
index 255fa51..e02f86d 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);
@@ -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)) {
@@ -249,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,
@@ -301,9 +289,7 @@ 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);
}
/* These are fixed point values in the 16.16 format. */
@@ -331,7 +317,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;
}
diff --git a/src/nv_accel_common.c b/src/nv_accel_common.c
index 89a0301..ea11cc6 100644
--- a/src/nv_accel_common.c
+++ b/src/nv_accel_common.c
@@ -22,6 +22,119 @@
#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_C0) {
+ if (height > 64)
+ tile_mode = 4;
+ else if (height > 32)
+ tile_mode = 3;
+ else if (height > 16)
+ tile_mode = 2;
+ else if (height > 8)
+ tile_mode = 1;
+ else
+ tile_mode = 0;
+
+ if (usage_hint & NOUVEAU_CREATE_PIXMAP_ZETA)
+ tile_flags = 0x1100; /* S8Z24 */
+ else
+ tile_flags = 0xfe00;
+
+ height = NOUVEAU_ALIGN(height, 1 << (tile_mode + 3));
+ } else 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, BoxPtr box)
+{
+ 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, box->x1, box->y1,
+ box->x2 - box->x1,
+ box->y2 - box->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_const.h b/src/nv_const.h
index 0df25b6..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__
@@ -13,6 +11,9 @@ typedef enum {
OPTION_NOACCEL,
OPTION_SHADOW_FB,
OPTION_VIDEO_KEY,
+ OPTION_WFB,
+ OPTION_GLX_VBLANK,
+ OPTION_ZAPHOD_HEADS,
} NVOpts;
@@ -22,6 +23,9 @@ 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_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_dma.c b/src/nv_dma.c
index 975bfeb..612215c 100644
--- a/src/nv_dma.c
+++ b/src/nv_dma.c
@@ -81,7 +81,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 f83762f..b7edf53 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.
@@ -206,6 +207,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;
@@ -281,6 +283,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;
}
@@ -357,6 +365,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,
@@ -369,9 +387,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;
@@ -418,9 +433,10 @@ NVCloseScreen(int scrnIndex, ScreenPtr pScreen)
ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
NVPtr pNv = NVPTR(pScrn);
- drmmode_uevent_fini(pScrn);
+ drmmode_screen_fini(pScreen);
- nouveau_dri2_fini(pScreen);
+ if (!pNv->NoAccel)
+ nouveau_dri2_fini(pScreen);
if (pScrn->vtSema) {
NVLeaveVT(scrnIndex, 0);
@@ -434,6 +450,8 @@ NVCloseScreen(int scrnIndex, ScreenPtr pScreen)
xf86_cursors_fini(pScreen);
+ DeleteCallback(&FlushCallback, NVFlushCallback, pScrn);
+
if (pNv->ShadowPtr) {
free(pNv->ShadowPtr);
pNv->ShadowPtr = NULL;
@@ -578,6 +596,7 @@ NVPreInit(ScrnInfoPtr pScrn, int flags)
struct nouveau_device *dev;
NVPtr pNv;
MessageType from;
+ uint64_t v;
int ret, i;
if (flags & PROBE_DETECT) {
@@ -618,10 +637,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))
@@ -680,8 +707,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:
@@ -766,11 +793,33 @@ NVPreInit(ScrnInfoPtr pScrn, int flags)
"Using \"Shadow Framebuffer\" - acceleration disabled\n");
}
- if (!pNv->NoAccel && pNv->Architecture >= NV_ARCH_50) {
- pNv->wfb_enabled = TRUE;
+ if (!pNv->NoAccel) {
+ if (pNv->Architecture >= NV_ARCH_50)
+ pNv->wfb_enabled = xf86ReturnOptValBool(
+ pNv->Options, OPTION_WFB, FALSE);
+
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");
+ }
+
+#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);
@@ -794,16 +843,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;
@@ -845,41 +884,19 @@ NVMapMem(ScrnInfoPtr pScrn)
{
NVPtr pNv = NVPTR(pScrn);
struct nouveau_device *dev = pNv->dev;
- uint32_t tile_mode = 0, tile_flags = 0;
- int ret, size;
-
- size = pScrn->displayWidth * (pScrn->bitsPerPixel >> 3);
- if (pNv->Architecture >= NV_ARCH_50 && pNv->tiled_scanout) {
- tile_mode = 4;
- if (pNv->Architecture == NV_ARCH_C0) {
- tile_flags = 0xfe0;
- size *= NOUVEAU_ALIGN(pScrn->virtualY,
- (1 << (tile_mode + 3)));
- } else {
- tile_flags =
- pScrn->bitsPerPixel == 16 ? 0x7000 : 0x7a00;
- size *= NOUVEAU_ALIGN(pScrn->virtualY,
- (1 << (tile_mode + 2)));
- }
- } else {
- size *= pScrn->virtualY;
- }
+ int ret, pitch, size;
- xf86DrvMsg(pScrn->scrnIndex, X_INFO,
- "new scanout bo: tile_mode=%x, tile_flags=%x\n",
- tile_mode, tile_flags);
-
- ret = nouveau_bo_new_tile(dev, NOUVEAU_BO_VRAM | NOUVEAU_BO_MAP,
- 1 << 17, 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;
@@ -1160,6 +1177,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;
@@ -1191,7 +1211,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_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__
diff --git a/src/nv_proto.h b/src/nv_proto.h
index 8d3a988..61a7b5b 100644
--- a/src/nv_proto.h
+++ b/src/nv_proto.h
@@ -7,8 +7,9 @@ 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);
+Bool drmmode_page_flip(DrawablePtr draw, PixmapPtr back, void *priv);
+void drmmode_screen_init(ScreenPtr pScreen);
+void drmmode_screen_fini(ScreenPtr pScreen);
/* in nv_accel_common.c */
Bool NVAccelCommonInit(ScrnInfoPtr pScrn);
@@ -16,15 +17,21 @@ 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, BoxPtr box);
+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,
+ unsigned int tv_sec, unsigned int tv_usec,
+ void *event_data);
Bool nouveau_dri2_init(ScreenPtr pScreen);
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 +132,7 @@ int NV40GetTexturePortAttribute(ScrnInfoPtr, Atom, INT32 *, pointer);
int NV40SetTexturePortAttribute(ScrnInfoPtr, Atom, INT32, pointer);
/* in nv50_accel.c */
+void NV50SyncToVBlank(PixmapPtr ppix, BoxPtr box);
Bool NVAccelInitNV50TCL(ScrnInfoPtr pScrn);
/* in nvc0_accel.c */
diff --git a/src/nv_type.h b/src/nv_type.h
index a6398a2..a06859d 100644
--- a/src/nv_type.h
+++ b/src/nv_type.h
@@ -37,6 +37,7 @@ typedef struct _NVRec {
EntityInfoPtr pEnt;
struct pci_device *PciInfo;
Bool Primary;
+ Bool Secondary;
/* Various pinned memory regions */
struct nouveau_bo * scanout;
@@ -54,6 +55,8 @@ typedef struct _NVRec {
Bool exa_force_cp;
Bool wfb_enabled;
Bool tiled_scanout;
+ Bool glx_vblank;
+ Bool has_pageflip;
ScreenBlockHandlerProcPtr BlockHandler;
CreateScreenResourcesProcPtr CreateScreenResources;
CloseScreenProcPtr CloseScreen;
@@ -154,8 +157,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;