diff --git a/libdrm/intel/intel_bufmgr.c b/libdrm/intel/intel_bufmgr.c index 92b6046..0d1909f 100644 --- a/libdrm/intel/intel_bufmgr.c +++ b/libdrm/intel/intel_bufmgr.c @@ -184,10 +184,10 @@ dri_bo_unpin(dri_bo *bo) return -ENODEV; } -int dri_bo_set_tiling(dri_bo *bo, uint32_t *tiling_mode) +int dri_bo_set_tiling(dri_bo *bo, uint32_t *tiling_mode, int stride) { if (bo->bufmgr->bo_set_tiling) - return bo->bufmgr->bo_set_tiling(bo, tiling_mode); + return bo->bufmgr->bo_set_tiling(bo, tiling_mode, stride); *tiling_mode = I915_TILING_NONE; return 0; diff --git a/libdrm/intel/intel_bufmgr.h b/libdrm/intel/intel_bufmgr.h index 0c7b0e4..885e24d 100644 --- a/libdrm/intel/intel_bufmgr.h +++ b/libdrm/intel/intel_bufmgr.h @@ -48,6 +48,13 @@ struct _dri_bo { */ unsigned long size; /** + * Alignment requirement for object + * + * Used for GTT mapping & pinning the object. + */ + unsigned long align; + + /** * Card virtual address (offset from the beginning of the aperture) for the * object. Only valid while validated. */ @@ -86,7 +93,7 @@ int dri_bo_emit_reloc(dri_bo *reloc_buf, uint32_t delta, uint32_t offset, dri_bo *target_buf); int dri_bo_pin(dri_bo *buf, uint32_t alignment); int dri_bo_unpin(dri_bo *buf); -int dri_bo_set_tiling(dri_bo *buf, uint32_t *tiling_mode); +int dri_bo_set_tiling(dri_bo *buf, uint32_t *tiling_mode, int stride); int dri_bo_get_tiling(dri_bo *buf, uint32_t *tiling_mode, uint32_t *swizzle_mode); int dri_bo_flink(dri_bo *buf, uint32_t *name); @@ -125,5 +132,7 @@ void intel_bo_fake_disable_backing_store(dri_bo *bo, void intel_bufmgr_fake_contended_lock_take(dri_bufmgr *bufmgr); void intel_bufmgr_fake_evict_all(dri_bufmgr *bufmgr); +int dri_gem_bo_map_gtt(dri_bo *bo, uint32_t alignment); + #endif /* INTEL_BUFMGR_H */ diff --git a/libdrm/intel/intel_bufmgr_gem.c b/libdrm/intel/intel_bufmgr_gem.c index 081eb2a..518280b 100644 --- a/libdrm/intel/intel_bufmgr_gem.c +++ b/libdrm/intel/intel_bufmgr_gem.c @@ -39,6 +39,7 @@ #endif #include +#include #include #include #include @@ -47,6 +48,8 @@ #include #include #include +#include +#include #include "errno.h" #include "intel_bufmgr.h" @@ -542,6 +545,86 @@ dri_gem_bo_map(dri_bo *bo, int write_enable) return 0; } +int +dri_gem_bo_map_gtt(dri_bo *bo, uint32_t alignment) +{ + dri_bufmgr_gem *bufmgr_gem; + dri_bo_gem *bo_gem = (dri_bo_gem *)bo; + struct drm_i915_gem_set_domain set_domain; + int ret; + + pthread_mutex_lock(&bufmgr_gem->lock); + + bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr; + + /* Allow recursive mapping. Mesa may recursively map buffers with + * nested display loops. + */ + if (!bo_gem->mapped) { + + assert(bo->virtual == NULL); + + DBG("bo_map_gtt: %d (%s)\n", bo_gem->gem_handle, bo_gem->name); + + if (bo_gem->virtual == NULL) { + struct drm_i915_gem_mmap_gtt mmap_arg; + + memset(&mmap_arg, 0, sizeof(mmap_arg)); + mmap_arg.handle = bo_gem->gem_handle; + /* Just map the whole object */ + mmap_arg.offset = 0; + mmap_arg.size = bo->size; + mmap_arg.alignment = alignment; + + ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_MMAP_GTT, + &mmap_arg); + if (ret != 0) { + fprintf(stderr, + "%s:%d: Error preparing buffer map %d (%s): %s .\n", + __FILE__, __LINE__, + bo_gem->gem_handle, bo_gem->name, + strerror(errno)); + pthread_mutex_unlock(&bufmgr_gem->lock); + return ret; + } + bo_gem->virtual = mmap(0, bo->size, PROT_READ | PROT_WRITE, + MAP_SHARED, bufmgr_gem->fd, + mmap_arg.addr_ptr); + if (bo_gem->virtual == MAP_FAILED) { + fprintf(stderr, + "%s:%d: Error mapping buffer %d (%s): %s .\n", + __FILE__, __LINE__, + bo_gem->gem_handle, bo_gem->name, + strerror(errno)); + pthread_mutex_unlock(&bufmgr_gem->lock); + return errno; + } + } + + bo->virtual = bo_gem->virtual; + bo_gem->mapped = 1; + DBG("bo_map: %d (%s) -> %p\n", bo_gem->gem_handle, bo_gem->name, + bo_gem->virtual); + } + + set_domain.handle = bo_gem->gem_handle; + set_domain.read_domains = I915_GEM_DOMAIN_GTT; + set_domain.write_domain = I915_GEM_DOMAIN_GTT; + do { + ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_SET_DOMAIN, + &set_domain); + } while (ret == -1 && errno == EINTR); + + if (ret != 0) { + fprintf (stderr, "%s:%d: Error setting swrast %d: %s\n", + __FILE__, __LINE__, bo_gem->gem_handle, strerror (errno)); + } + + pthread_mutex_unlock(&bufmgr_gem->lock); + + return 0; +} + static int dri_gem_bo_unmap(dri_bo *bo) { @@ -852,7 +935,7 @@ dri_gem_bo_unpin(dri_bo *bo) } static int -dri_gem_bo_set_tiling(dri_bo *bo, uint32_t *tiling_mode) +dri_gem_bo_set_tiling(dri_bo *bo, uint32_t *tiling_mode, int stride) { dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr; dri_bo_gem *bo_gem = (dri_bo_gem *)bo; @@ -861,6 +944,7 @@ dri_gem_bo_set_tiling(dri_bo *bo, uint32_t *tiling_mode) set_tiling.handle = bo_gem->gem_handle; set_tiling.tiling_mode = *tiling_mode; + set_tiling.stride = stride; ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_SET_TILING, &set_tiling); if (ret != 0) { diff --git a/libdrm/intel/intel_bufmgr_priv.h b/libdrm/intel/intel_bufmgr_priv.h index cbf3b31..b5603b8 100644 --- a/libdrm/intel/intel_bufmgr_priv.h +++ b/libdrm/intel/intel_bufmgr_priv.h @@ -147,8 +147,9 @@ struct _dri_bufmgr { * * \param buf Buffer to set tiling mode for * \param tiling_mode desired, and returned tiling mode + * \param stride pitch of buffer */ - int (*bo_set_tiling) (dri_bo *bo, uint32_t *tiling_mode); + int (*bo_set_tiling) (dri_bo *bo, uint32_t *tiling_mode, int stride); /** * Get the current tiling (and resulting swizzling) mode for the bo. * diff --git a/shared-core/i915_drm.h b/shared-core/i915_drm.h index 2801687..4b70df9 100644 --- a/shared-core/i915_drm.h +++ b/shared-core/i915_drm.h @@ -192,6 +192,7 @@ typedef struct drm_i915_sarea { #define DRM_I915_GEM_SW_FINISH 0x20 #define DRM_I915_GEM_SET_TILING 0x21 #define DRM_I915_GEM_GET_TILING 0x22 +#define DRM_I915_GEM_MMAP_GTT 0x23 #define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t) #define DRM_IOCTL_I915_FLUSH DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH) @@ -223,6 +224,7 @@ typedef struct drm_i915_sarea { #define DRM_IOCTL_I915_GEM_PREAD DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_PREAD, struct drm_i915_gem_pread) #define DRM_IOCTL_I915_GEM_PWRITE DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_PWRITE, struct drm_i915_gem_pwrite) #define DRM_IOCTL_I915_GEM_MMAP DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_MMAP, struct drm_i915_gem_mmap) +#define DRM_IOCTL_I915_GEM_MMAP_GTT DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_MMAP_GTT, struct drm_i915_gem_mmap_gtt) #define DRM_IOCTL_I915_GEM_SET_DOMAIN DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_SET_DOMAIN, struct drm_i915_gem_set_domain) #define DRM_IOCTL_I915_GEM_SW_FINISH DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_SW_FINISH, struct drm_i915_gem_sw_finish) #define DRM_IOCTL_I915_GEM_SET_TILING DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_SET_TILING, struct drm_i915_gem_set_tiling) @@ -497,6 +499,24 @@ struct drm_i915_gem_mmap { uint64_t addr_ptr; /* void *, but pointers are not 32/64 compatible */ }; +struct drm_i915_gem_mmap_gtt { + /** Handle for the object being mapped. */ + uint32_t handle; + uint32_t pad; + /** Offset in the object to map. */ + uint64_t offset; + /** + * Length of data to map. + * + * The value will be page-aligned. + */ + uint64_t size; + /** Returned pointer the data was mapped at */ + uint64_t addr_ptr; /* void *, but pointers are not 32/64 compatible */ + uint32_t flags; + uint32_t alignment; +}; + struct drm_i915_gem_set_domain { /** Handle for the object */ uint32_t handle;