diff options
author | Christoph Bumiller <e0425955@student.tuwien.ac.at> | 2010-12-09 01:31:40 +0100 |
---|---|---|
committer | Christoph Bumiller <e0425955@student.tuwien.ac.at> | 2010-12-09 01:31:40 +0100 |
commit | 178356391ff6831599eba257a5912079894641a1 (patch) | |
tree | 34a0d4d1bb0b7d7050abb981a7fdd10313687cb8 /src | |
parent | 8573280871401e29f27fa24d0b7c6ac5e35b2cc1 (diff) | |
parent | 8bb8231236a6b877895663aeaa9cef731d67fe68 (diff) |
Merge remote branch 'origin/master' into nvc0
Conflicts:
src/drmmode_display.c
src/nouveau_exa.c
src/nv_driver.c
src/nv_type.h
Diffstat (limited to 'src')
-rw-r--r-- | src/drmmode_display.c | 277 | ||||
-rw-r--r-- | src/nouveau_class.h | 2 | ||||
-rw-r--r-- | src/nouveau_dri2.c | 298 | ||||
-rw-r--r-- | src/nouveau_exa.c | 111 | ||||
-rw-r--r-- | src/nouveau_local.h | 11 | ||||
-rw-r--r-- | src/nouveau_wfb.c | 2 | ||||
-rw-r--r-- | src/nouveau_xv.c | 20 | ||||
-rw-r--r-- | src/nv04_exa.c | 39 | ||||
-rw-r--r-- | src/nv04_xv_blit.c | 11 | ||||
-rw-r--r-- | src/nv30_xv_tex.c | 19 | ||||
-rw-r--r-- | src/nv40_xv_tex.c | 19 | ||||
-rw-r--r-- | src/nv50_accel.c | 33 | ||||
-rw-r--r-- | src/nv50_xv.c | 52 | ||||
-rw-r--r-- | src/nv_accel_common.c | 113 | ||||
-rw-r--r-- | src/nv_const.h | 8 | ||||
-rw-r--r-- | src/nv_dma.c | 3 | ||||
-rw-r--r-- | src/nv_driver.c | 123 | ||||
-rw-r--r-- | src/nv_include.h | 2 | ||||
-rw-r--r-- | src/nv_proto.h | 14 | ||||
-rw-r--r-- | src/nv_type.h | 8 |
20 files changed, 844 insertions, 321 deletions
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, ®, (&(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); + 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, ®)); + else + NV11SyncToVBlank(dst_pix, REGION_EXTENTS(0, ®)); + + FIRE_RING(chan); + } + + if (can_exchange(draw, dst_pix, src_pix)) { + type = DRI2_EXCHANGE_COMPLETE; + DamageRegionAppend(draw, ®); + + 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, ®, -draw->x, -draw->y); + nouveau_dri2_copy_region(draw, ®, 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, + ¤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; +} + +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, + ¤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)) { + *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; |