From 3d4bfe8c893d016ef43d1ebf28e4607aa1f540a4 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 3 Jun 2009 13:54:43 +1000 Subject: [PATCH] nouveau: 0.0.14 + extend bo interface to support subrange mapping Normal map() should operate as before, and map_range()/map_flush() should give correct results but lacking any performance difference from map(). Nothing exiting being done here yet, but the interface is a good start. --- libdrm/nouveau/libdrm_nouveau.pc.in | 2 +- libdrm/nouveau/nouveau_bo.c | 78 +++++++++++++++++------------ libdrm/nouveau/nouveau_bo.h | 19 ++++++- libdrm/nouveau/nouveau_device.c | 2 +- libdrm/nouveau/nouveau_pushbuf.c | 4 +- libdrm/nouveau/nouveau_pushbuf.h | 23 +++++++-- shared-core/nouveau_drm.h | 6 +-- shared-core/nouveau_drv.h | 2 +- 8 files changed, 93 insertions(+), 43 deletions(-) diff --git a/libdrm/nouveau/libdrm_nouveau.pc.in b/libdrm/nouveau/libdrm_nouveau.pc.in index 9e67a239..7ef49e5a 100644 --- a/libdrm/nouveau/libdrm_nouveau.pc.in +++ b/libdrm/nouveau/libdrm_nouveau.pc.in @@ -5,6 +5,6 @@ includedir=@includedir@ Name: libdrm_nouveau Description: Userspace interface to nouveau kernel DRM services -Version: 0.5 +Version: 0.6 Libs: -L${libdir} -ldrm_nouveau Cflags: -I${includedir} -I${includedir}/drm -I${includedir}/nouveau diff --git a/libdrm/nouveau/nouveau_bo.c b/libdrm/nouveau/nouveau_bo.c index 55d0575b..e68533b7 100644 --- a/libdrm/nouveau/nouveau_bo.c +++ b/libdrm/nouveau/nouveau_bo.c @@ -52,15 +52,8 @@ nouveau_bo_info(struct nouveau_bo_priv *nvbo, struct drm_nouveau_gem_info *arg) nvbo->size = nvbo->base.size = arg->size; nvbo->offset = arg->offset; nvbo->map_handle = arg->map_handle; - - if (nvbo->domain & NOUVEAU_GEM_DOMAIN_TILE) { - nvbo->base.tiled = 1; - if (nvbo->domain & NOUVEAU_GEM_DOMAIN_TILE_ZETA) - nvbo->base.tiled |= 2; - } else { - nvbo->base.tiled = 0; - } - + nvbo->base.tile_mode = arg->tile_mode; + nvbo->base.tile_flags = arg->tile_flags; return 0; } @@ -215,18 +208,15 @@ nouveau_bo_kalloc(struct nouveau_bo_priv *nvbo, struct nouveau_channel *chan) info->domain |= NOUVEAU_GEM_DOMAIN_GART; if (!info->domain) { info->domain |= (NOUVEAU_GEM_DOMAIN_VRAM | - NOUVEAU_GEM_DOMAIN_GART); - } - - if (nvbo->flags & NOUVEAU_BO_TILED) { - info->domain |= NOUVEAU_GEM_DOMAIN_TILE; - if (nvbo->flags & NOUVEAU_BO_ZTILE) - info->domain |= NOUVEAU_GEM_DOMAIN_TILE_ZETA; + NOUVEAU_GEM_DOMAIN_GART); } if (nvbo->flags & NOUVEAU_BO_MAP) info->domain |= NOUVEAU_GEM_DOMAIN_MAPPABLE; + info->tile_mode = nvbo->base.tile_mode; + info->tile_flags = nvbo->base.tile_flags; + ret = drmCommandWriteRead(nvdev->fd, DRM_NOUVEAU_GEM_NEW, &req, sizeof(req)); if (ret) @@ -276,8 +266,9 @@ nouveau_bo_kmap(struct nouveau_bo_priv *nvbo) } int -nouveau_bo_new(struct nouveau_device *dev, uint32_t flags, int align, - int size, struct nouveau_bo **bo) +nouveau_bo_new_tile(struct nouveau_device *dev, uint32_t flags, int align, + int size, uint32_t tile_mode, uint32_t tile_flags, + struct nouveau_bo **bo) { struct nouveau_bo_priv *nvbo; int ret; @@ -290,6 +281,8 @@ nouveau_bo_new(struct nouveau_device *dev, uint32_t flags, int align, return -ENOMEM; nvbo->base.device = dev; nvbo->base.size = size; + nvbo->base.tile_mode = tile_mode; + nvbo->base.tile_flags = tile_flags; nvbo->refcount = 1; /* Don't set NOUVEAU_BO_PIN here, or nouveau_bo_allocated() will @@ -300,13 +293,6 @@ nouveau_bo_new(struct nouveau_device *dev, uint32_t flags, int align, nvbo->size = size; nvbo->align = align; - /*XXX: murder me violently */ - if (flags & NOUVEAU_BO_TILED) { - nvbo->base.tiled = 1; - if (flags & NOUVEAU_BO_ZTILE) - nvbo->base.tiled |= 2; - } - if (flags & NOUVEAU_BO_PIN) { ret = nouveau_bo_pin((void *)nvbo, nvbo->flags); if (ret) { @@ -319,6 +305,22 @@ nouveau_bo_new(struct nouveau_device *dev, uint32_t flags, int align, return 0; } +int +nouveau_bo_new(struct nouveau_device *dev, uint32_t flags, int align, + int size, struct nouveau_bo **bo) +{ + uint32_t tile_flags = 0; + + if (flags & NOUVEAU_BO_TILED) { + if (flags & NOUVEAU_BO_ZTILE) + tile_flags = 0x2800; + else + tile_flags = 0x7000; + } + + return nouveau_bo_new_tile(dev, flags, align, size, 0, tile_flags, bo); +} + int nouveau_bo_user(struct nouveau_device *dev, void *ptr, int size, struct nouveau_bo **bo) @@ -575,7 +577,8 @@ nouveau_bo_wait(struct nouveau_bo *bo, int cpu_write) } int -nouveau_bo_map(struct nouveau_bo *bo, uint32_t flags) +nouveau_bo_map_range(struct nouveau_bo *bo, uint32_t delta, uint32_t size, + uint32_t flags) { struct nouveau_bo_priv *nvbo = nouveau_bo(bo); int ret; @@ -598,22 +601,35 @@ nouveau_bo_map(struct nouveau_bo *bo, uint32_t flags) } if (nvbo->sysmem) { - bo->map = nvbo->sysmem; + bo->map = (char *)nvbo->sysmem + delta; } else { ret = nouveau_bo_kmap(nvbo); if (ret) return ret; - ret = nouveau_bo_wait(bo, (flags & NOUVEAU_BO_WR)); - if (ret) - return ret; + if (!(flags & NOUVEAU_BO_NOSYNC)) { + ret = nouveau_bo_wait(bo, (flags & NOUVEAU_BO_WR)); + if (ret) + return ret; + } - bo->map = nvbo->map; + bo->map = (char *)nvbo->map + delta; } return 0; } +void +nouveau_bo_map_flush(struct nouveau_bo *bo, uint32_t delta, uint32_t size) +{ +} + +int +nouveau_bo_map(struct nouveau_bo *bo, uint32_t flags) +{ + return nouveau_bo_map_range(bo, 0, bo->size, flags); +} + void nouveau_bo_unmap(struct nouveau_bo *bo) { diff --git a/libdrm/nouveau/nouveau_bo.h b/libdrm/nouveau/nouveau_bo.h index f0ae09be..9b1feff1 100644 --- a/libdrm/nouveau/nouveau_bo.h +++ b/libdrm/nouveau/nouveau_bo.h @@ -37,6 +37,10 @@ #define NOUVEAU_BO_LOCAL (1 << 9) #define NOUVEAU_BO_TILED (1 << 10) #define NOUVEAU_BO_ZTILE (1 << 11) +#define NOUVEAU_BO_INVAL (1 << 12) +#define NOUVEAU_BO_NOSYNC (1 << 13) +#define NOUVEAU_BO_NOWAIT (1 << 14) +#define NOUVEAU_BO_IFLUSH (1 << 15) #define NOUVEAU_BO_DUMMY (1 << 31) struct nouveau_bo { @@ -46,7 +50,8 @@ struct nouveau_bo { uint64_t size; void *map; - int tiled; + uint32_t tile_mode; + uint32_t tile_flags; /* Available when buffer is pinned *only* */ uint32_t flags; @@ -57,6 +62,11 @@ int nouveau_bo_new(struct nouveau_device *, uint32_t flags, int align, int size, struct nouveau_bo **); +int +nouveau_bo_new_tile(struct nouveau_device *, uint32_t flags, int align, + int size, uint32_t tile_mode, uint32_t tile_flags, + struct nouveau_bo **); + int nouveau_bo_user(struct nouveau_device *, void *ptr, int size, struct nouveau_bo **); @@ -78,6 +88,13 @@ nouveau_bo_handle_ref(struct nouveau_device *, uint32_t handle, int nouveau_bo_ref(struct nouveau_bo *, struct nouveau_bo **); +int +nouveau_bo_map_range(struct nouveau_bo *, uint32_t delta, uint32_t size, + uint32_t flags); + +void +nouveau_bo_map_flush(struct nouveau_bo *, uint32_t delta, uint32_t size); + int nouveau_bo_map(struct nouveau_bo *, uint32_t flags); diff --git a/libdrm/nouveau/nouveau_device.c b/libdrm/nouveau/nouveau_device.c index 48db23d8..6b99e369 100644 --- a/libdrm/nouveau/nouveau_device.c +++ b/libdrm/nouveau/nouveau_device.c @@ -26,7 +26,7 @@ #include "nouveau_private.h" -#if NOUVEAU_DRM_HEADER_PATCHLEVEL != 13 +#if NOUVEAU_DRM_HEADER_PATCHLEVEL != 14 #error nouveau_drm.h does not match expected patchlevel, update libdrm. #endif diff --git a/libdrm/nouveau/nouveau_pushbuf.c b/libdrm/nouveau/nouveau_pushbuf.c index 5b8d18b9..fded21b9 100644 --- a/libdrm/nouveau/nouveau_pushbuf.c +++ b/libdrm/nouveau/nouveau_pushbuf.c @@ -60,8 +60,8 @@ nouveau_pushbuf_calc_reloc(struct drm_nouveau_gem_pushbuf_bo *pbbo, int nouveau_pushbuf_emit_reloc(struct nouveau_channel *chan, void *ptr, - struct nouveau_bo *bo, uint32_t data, uint32_t flags, - uint32_t vor, uint32_t tor) + struct nouveau_bo *bo, uint32_t data, uint32_t data2, + uint32_t flags, uint32_t vor, uint32_t tor) { struct nouveau_device_priv *nvdev = nouveau_device(chan->device); struct nouveau_pushbuf_priv *nvpb = nouveau_pushbuf(chan->pushbuf); diff --git a/libdrm/nouveau/nouveau_pushbuf.h b/libdrm/nouveau/nouveau_pushbuf.h index 414ad2d8..3c746ed2 100644 --- a/libdrm/nouveau/nouveau_pushbuf.h +++ b/libdrm/nouveau/nouveau_pushbuf.h @@ -41,8 +41,8 @@ nouveau_pushbuf_flush(struct nouveau_channel *, unsigned min); int nouveau_pushbuf_emit_reloc(struct nouveau_channel *, void *ptr, - struct nouveau_bo *, uint32_t data, uint32_t flags, - uint32_t vor, uint32_t tor); + struct nouveau_bo *, uint32_t data, uint32_t data2, + uint32_t flags, uint32_t vor, uint32_t tor); /* Push buffer access macros */ static __inline__ void @@ -121,7 +121,16 @@ OUT_RELOC(struct nouveau_channel *chan, struct nouveau_bo *bo, unsigned data, unsigned flags, unsigned vor, unsigned tor) { nouveau_pushbuf_emit_reloc(chan, chan->pushbuf->cur++, bo, - data, flags, vor, tor); + data, 0, flags, vor, tor); +} + +static __inline__ void +OUT_RELOC2(struct nouveau_channel *chan, struct nouveau_bo *bo, + unsigned data, unsigned data2, unsigned flags, + unsigned vor, unsigned tor) +{ + nouveau_pushbuf_emit_reloc(chan, chan->pushbuf->cur++, bo, + data, data2, flags, vor, tor); } /* Raw data + flags depending on FB/TT buffer */ @@ -149,6 +158,14 @@ OUT_RELOCl(struct nouveau_channel *chan, struct nouveau_bo *bo, OUT_RELOC(chan, bo, delta, flags | NOUVEAU_BO_LOW, 0, 0); } +/* Low 32-bits of offset + GPU linear access range info */ +static __inline__ void +OUT_RELOCr(struct nouveau_channel *chan, struct nouveau_bo *bo, + unsigned delta, unsigned size, unsigned flags) +{ + OUT_RELOC2(chan, bo, delta, size, flags | NOUVEAU_BO_LOW, 0, 0); +} + /* High 32-bits of offset */ static __inline__ void OUT_RELOCh(struct nouveau_channel *chan, struct nouveau_bo *bo, diff --git a/shared-core/nouveau_drm.h b/shared-core/nouveau_drm.h index e999d20d..dc6a1945 100644 --- a/shared-core/nouveau_drm.h +++ b/shared-core/nouveau_drm.h @@ -25,7 +25,7 @@ #ifndef __NOUVEAU_DRM_H__ #define __NOUVEAU_DRM_H__ -#define NOUVEAU_DRM_HEADER_PATCHLEVEL 13 +#define NOUVEAU_DRM_HEADER_PATCHLEVEL 14 struct drm_nouveau_channel_alloc { uint32_t fb_ctxdma_handle; @@ -154,8 +154,6 @@ struct drm_nouveau_setparam { #define NOUVEAU_GEM_DOMAIN_VRAM (1 << 1) #define NOUVEAU_GEM_DOMAIN_GART (1 << 2) #define NOUVEAU_GEM_DOMAIN_MAPPABLE (1 << 3) -#define NOUVEAU_GEM_DOMAIN_TILE (1 << 30) -#define NOUVEAU_GEM_DOMAIN_TILE_ZETA (1 << 31) struct drm_nouveau_gem_info { uint32_t handle; @@ -163,6 +161,8 @@ struct drm_nouveau_gem_info { uint64_t size; uint64_t offset; uint64_t map_handle; + uint32_t tile_mode; + uint32_t tile_flags; }; struct drm_nouveau_gem_new { diff --git a/shared-core/nouveau_drv.h b/shared-core/nouveau_drv.h index ce52ce27..841cbf53 100644 --- a/shared-core/nouveau_drv.h +++ b/shared-core/nouveau_drv.h @@ -34,7 +34,7 @@ #define DRIVER_MAJOR 0 #define DRIVER_MINOR 0 -#define DRIVER_PATCHLEVEL 13 +#define DRIVER_PATCHLEVEL 14 #define NOUVEAU_FAMILY 0x0000FFFF #define NOUVEAU_FLAGS 0xFFFF0000