diff --git a/intel/intel_bufmgr_gem.c b/intel/intel_bufmgr_gem.c index a8e072d..3446390 100644 --- a/intel/intel_bufmgr_gem.c +++ b/intel/intel_bufmgr_gem.c @@ -93,6 +93,7 @@ typedef struct _drm_intel_bufmgr_gem { /** Array of lists of cached gem objects of power-of-two sizes */ struct drm_intel_gem_bo_bucket cache_bucket[14 * 4]; int num_buckets; + time_t time; uint64_t gtt_size; int available_fences; @@ -132,6 +133,7 @@ struct _drm_intel_bo_gem { */ uint32_t tiling_mode; uint32_t swizzle_mode; + unsigned long stride; time_t free_time; @@ -200,8 +202,9 @@ drm_intel_gem_bo_get_tiling(drm_intel_bo *bo, uint32_t * tiling_mode, uint32_t * swizzle_mode); static int -drm_intel_gem_bo_set_tiling(drm_intel_bo *bo, uint32_t * tiling_mode, - uint32_t stride); +drm_intel_gem_bo_set_tiling_internal(drm_intel_bo *bo, + uint32_t tiling_mode, + uint32_t stride); static void drm_intel_gem_bo_unreference_locked_timed(drm_intel_bo *bo, time_t time); @@ -251,7 +254,7 @@ drm_intel_gem_bo_tile_size(drm_intel_bufmgr_gem *bufmgr_gem, unsigned long size, */ static unsigned long drm_intel_gem_bo_tile_pitch(drm_intel_bufmgr_gem *bufmgr_gem, - unsigned long pitch, uint32_t tiling_mode) + unsigned long pitch, uint32_t *tiling_mode) { unsigned long tile_width; unsigned long i; @@ -259,10 +262,10 @@ drm_intel_gem_bo_tile_pitch(drm_intel_bufmgr_gem *bufmgr_gem, /* If untiled, then just align it so that we can do rendering * to it with the 3D engine. */ - if (tiling_mode == I915_TILING_NONE) + if (*tiling_mode == I915_TILING_NONE) return ALIGN(pitch, 64); - if (tiling_mode == I915_TILING_X) + if (*tiling_mode == I915_TILING_X) tile_width = 512; else tile_width = 128; @@ -271,6 +274,14 @@ drm_intel_gem_bo_tile_pitch(drm_intel_bufmgr_gem *bufmgr_gem, if (bufmgr_gem->gen >= 4) return ROUND_UP_TO(pitch, tile_width); + /* The older hardware has a maximum pitch of 8192 with tiled + * surfaces, so fallback to untiled if it's too large. + */ + if (pitch > 8192) { + *tiling_mode = I915_TILING_NONE; + return ALIGN(pitch, 64); + } + /* Pre-965 needs power of two tile width */ for (i = tile_width; i < pitch; i <<= 1) ; @@ -549,7 +560,9 @@ static drm_intel_bo * drm_intel_gem_bo_alloc_internal(drm_intel_bufmgr *bufmgr, const char *name, unsigned long size, - unsigned long flags) + unsigned long flags, + uint32_t tiling_mode, + unsigned long stride) { drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bufmgr; drm_intel_bo_gem *bo_gem; @@ -615,6 +628,13 @@ retry: bucket); goto retry; } + + if (drm_intel_gem_bo_set_tiling_internal(&bo_gem->bo, + tiling_mode, + stride)) { + drm_intel_gem_bo_free(&bo_gem->bo); + goto retry; + } } } pthread_mutex_unlock(&bufmgr_gem->lock); @@ -642,6 +662,17 @@ retry: return NULL; } bo_gem->bo.bufmgr = bufmgr; + + bo_gem->tiling_mode = I915_TILING_NONE; + bo_gem->swizzle_mode = I915_BIT_6_SWIZZLE_NONE; + bo_gem->stride = 0; + + if (drm_intel_gem_bo_set_tiling_internal(&bo_gem->bo, + tiling_mode, + stride)) { + drm_intel_gem_bo_free(&bo_gem->bo); + return NULL; + } } bo_gem->name = name; @@ -650,8 +681,6 @@ retry: bo_gem->reloc_tree_fences = 0; bo_gem->used_as_reloc_target = 0; bo_gem->has_error = 0; - bo_gem->tiling_mode = I915_TILING_NONE; - bo_gem->swizzle_mode = I915_BIT_6_SWIZZLE_NONE; bo_gem->reusable = 1; drm_intel_bo_gem_set_in_aperture_size(bufmgr_gem, bo_gem); @@ -669,7 +698,8 @@ drm_intel_gem_bo_alloc_for_render(drm_intel_bufmgr *bufmgr, unsigned int alignment) { return drm_intel_gem_bo_alloc_internal(bufmgr, name, size, - BO_ALLOC_FOR_RENDER); + BO_ALLOC_FOR_RENDER, + I915_TILING_NONE, 0); } static drm_intel_bo * @@ -678,7 +708,8 @@ drm_intel_gem_bo_alloc(drm_intel_bufmgr *bufmgr, unsigned long size, unsigned int alignment) { - return drm_intel_gem_bo_alloc_internal(bufmgr, name, size, 0); + return drm_intel_gem_bo_alloc_internal(bufmgr, name, size, 0, + I915_TILING_NONE, 0); } static drm_intel_bo * @@ -687,10 +718,8 @@ drm_intel_gem_bo_alloc_tiled(drm_intel_bufmgr *bufmgr, const char *name, unsigned long *pitch, unsigned long flags) { drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bufmgr; - drm_intel_bo *bo; unsigned long size, stride; uint32_t tiling; - int ret; do { unsigned long aligned_y; @@ -717,24 +746,17 @@ drm_intel_gem_bo_alloc_tiled(drm_intel_bufmgr *bufmgr, const char *name, aligned_y = ALIGN(y, 32); stride = x * cpp; - stride = drm_intel_gem_bo_tile_pitch(bufmgr_gem, stride, tiling); + stride = drm_intel_gem_bo_tile_pitch(bufmgr_gem, stride, tiling_mode); size = stride * aligned_y; size = drm_intel_gem_bo_tile_size(bufmgr_gem, size, tiling_mode); } while (*tiling_mode != tiling); - - bo = drm_intel_gem_bo_alloc_internal(bufmgr, name, size, flags); - if (!bo) - return NULL; - - ret = drm_intel_gem_bo_set_tiling(bo, tiling_mode, stride); - if (ret != 0) { - drm_intel_gem_bo_unreference(bo); - return NULL; - } - *pitch = stride; - return bo; + if (tiling == I915_TILING_NONE) + stride = 0; + + return drm_intel_gem_bo_alloc_internal(bufmgr, name, size, flags, + tiling, stride); } /** @@ -791,6 +813,7 @@ drm_intel_bo_gem_create_from_name(drm_intel_bufmgr *bufmgr, } bo_gem->tiling_mode = get_tiling.tiling_mode; bo_gem->swizzle_mode = get_tiling.swizzle_mode; + /* XXX stride is unknown */ drm_intel_bo_gem_set_in_aperture_size(bufmgr_gem, bo_gem); DBG("bo_create_from_handle: %d (%s)\n", handle, bo_gem->name); @@ -829,6 +852,9 @@ drm_intel_gem_cleanup_bo_cache(drm_intel_bufmgr_gem *bufmgr_gem, time_t time) { int i; + if (bufmgr_gem->time == time) + return; + for (i = 0; i < bufmgr_gem->num_buckets; i++) { struct drm_intel_gem_bo_bucket *bucket = &bufmgr_gem->cache_bucket[i]; @@ -846,6 +872,8 @@ drm_intel_gem_cleanup_bo_cache(drm_intel_bufmgr_gem *bufmgr_gem, time_t time) drm_intel_gem_bo_free(&bo_gem->bo); } } + + bufmgr_gem->time = time; } static void @@ -854,7 +882,6 @@ drm_intel_gem_bo_unreference_final(drm_intel_bo *bo, time_t time) drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; struct drm_intel_gem_bo_bucket *bucket; - uint32_t tiling_mode; int i; /* Unreference all the target buffers */ @@ -883,9 +910,7 @@ drm_intel_gem_bo_unreference_final(drm_intel_bo *bo, time_t time) bucket = drm_intel_gem_bo_bucket_for_size(bufmgr_gem, bo->size); /* Put the buffer into our internal cache for reuse if we can. */ - tiling_mode = I915_TILING_NONE; if (bufmgr_gem->bo_reuse && bo_gem->reusable && bucket != NULL && - drm_intel_gem_bo_set_tiling(bo, &tiling_mode, 0) == 0 && drm_intel_gem_bo_madvise_internal(bufmgr_gem, bo_gem, I915_MADV_DONTNEED)) { bo_gem->free_time = time; @@ -894,8 +919,6 @@ drm_intel_gem_bo_unreference_final(drm_intel_bo *bo, time_t time) bo_gem->validate_index = -1; DRMLISTADDTAIL(&bo_gem->head, &bucket->head); - - drm_intel_gem_cleanup_bo_cache(bufmgr_gem, time); } else { drm_intel_gem_bo_free(bo); } @@ -925,6 +948,7 @@ static void drm_intel_gem_bo_unreference(drm_intel_bo *bo) pthread_mutex_lock(&bufmgr_gem->lock); drm_intel_gem_bo_unreference_final(bo, time.tv_sec); + drm_intel_gem_cleanup_bo_cache(bufmgr_gem, time.tv_sec); pthread_mutex_unlock(&bufmgr_gem->lock); } } @@ -982,12 +1006,9 @@ static int drm_intel_gem_bo_map(drm_intel_bo *bo, int write_enable) &set_domain); } while (ret == -1 && errno == EINTR); if (ret != 0) { - ret = -errno; fprintf(stderr, "%s:%d: Error setting to CPU domain %d: %s\n", __FILE__, __LINE__, bo_gem->gem_handle, strerror(errno)); - pthread_mutex_unlock(&bufmgr_gem->lock); - return ret; } pthread_mutex_unlock(&bufmgr_gem->lock); @@ -1062,9 +1083,7 @@ int drm_intel_gem_bo_map_gtt(drm_intel_bo *bo) DRM_IOCTL_I915_GEM_SET_DOMAIN, &set_domain); } while (ret == -1 && errno == EINTR); - if (ret != 0) { - ret = -errno; fprintf(stderr, "%s:%d: Error setting domain %d: %s\n", __FILE__, __LINE__, bo_gem->gem_handle, strerror(errno)); @@ -1072,7 +1091,7 @@ int drm_intel_gem_bo_map_gtt(drm_intel_bo *bo) pthread_mutex_unlock(&bufmgr_gem->lock); - return ret; + return 0; } int drm_intel_gem_bo_unmap_gtt(drm_intel_bo *bo) @@ -1587,7 +1606,7 @@ drm_intel_gem_bo_mrb_exec2(drm_intel_bo *bo, int used, if (ret != 0) { ret = -errno; - if (ret == -ENOMEM) { + if (ret == -ENOSPC) { fprintf(stderr, "Execbuffer fails to pin. " "Estimate: %u. Actual: %u. Available: %u\n", @@ -1671,34 +1690,56 @@ drm_intel_gem_bo_unpin(drm_intel_bo *bo) } static int -drm_intel_gem_bo_set_tiling(drm_intel_bo *bo, uint32_t * tiling_mode, - uint32_t stride) +drm_intel_gem_bo_set_tiling_internal(drm_intel_bo *bo, + uint32_t tiling_mode, + uint32_t stride) { drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; struct drm_i915_gem_set_tiling set_tiling; int ret; - if (bo_gem->global_name == 0 && *tiling_mode == bo_gem->tiling_mode) + if (bo_gem->global_name == 0 && + tiling_mode == bo_gem->tiling_mode && + stride == bo_gem->stride) return 0; memset(&set_tiling, 0, sizeof(set_tiling)); - set_tiling.handle = bo_gem->gem_handle; - do { - set_tiling.tiling_mode = *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); } while (ret == -1 && errno == EINTR); - if (ret == 0) { - bo_gem->tiling_mode = set_tiling.tiling_mode; - bo_gem->swizzle_mode = set_tiling.swizzle_mode; + if (ret == -1) + return -errno; + + bo_gem->tiling_mode = set_tiling.tiling_mode; + bo_gem->swizzle_mode = set_tiling.swizzle_mode; + bo_gem->stride = set_tiling.stride; + return 0; +} + +static int +drm_intel_gem_bo_set_tiling(drm_intel_bo *bo, uint32_t * tiling_mode, + uint32_t stride) +{ + drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; + drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; + int ret; + + /* Linear buffers have no stride. By ensuring that we only ever use + * stride 0 with linear buffers, we simplify our code. + */ + if (*tiling_mode == I915_TILING_NONE) + stride = 0; + + ret = drm_intel_gem_bo_set_tiling_internal(bo, *tiling_mode, stride); + if (ret == 0) drm_intel_bo_gem_set_in_aperture_size(bufmgr_gem, bo_gem); - } else - ret = -errno; *tiling_mode = bo_gem->tiling_mode; return ret; diff --git a/xf86drmMode.c b/xf86drmMode.c index f330e6f..ecb1fd5 100644 --- a/xf86drmMode.c +++ b/xf86drmMode.c @@ -52,6 +52,12 @@ #define U642VOID(x) ((void *)(unsigned long)(x)) #define VOID2U64(x) ((uint64_t)(unsigned long)(x)) +static inline DRM_IOCTL(int fd, int cmd, void *arg) +{ + int ret = drmIoctl(fd, cmd, arg); + return ret < 0 ? -errno : ret; +} + /* * Util functions */ @@ -242,7 +248,7 @@ int drmModeAddFB(int fd, uint32_t width, uint32_t height, uint8_t depth, f.depth = depth; f.handle = bo_handle; - if ((ret = drmIoctl(fd, DRM_IOCTL_MODE_ADDFB, &f))) + if ((ret = DRM_IOCTL(fd, DRM_IOCTL_MODE_ADDFB, &f))) return ret; *buf_id = f.fb_id; @@ -251,7 +257,7 @@ int drmModeAddFB(int fd, uint32_t width, uint32_t height, uint8_t depth, int drmModeRmFB(int fd, uint32_t bufferId) { - return drmIoctl(fd, DRM_IOCTL_MODE_RMFB, &bufferId); + return DRM_IOCTL(fd, DRM_IOCTL_MODE_RMFB, &bufferId); } @@ -289,7 +295,7 @@ int drmModeDirtyFB(int fd, uint32_t bufferId, dirty.clips_ptr = VOID2U64(clips); dirty.num_clips = num_clips; - return drmIoctl(fd, DRM_IOCTL_MODE_DIRTYFB, &dirty); + return DRM_IOCTL(fd, DRM_IOCTL_MODE_DIRTYFB, &dirty); } @@ -344,7 +350,7 @@ int drmModeSetCrtc(int fd, uint32_t crtcId, uint32_t bufferId, } else crtc.mode_valid = 0; - return drmIoctl(fd, DRM_IOCTL_MODE_SETCRTC, &crtc); + return DRM_IOCTL(fd, DRM_IOCTL_MODE_SETCRTC, &crtc); } /* @@ -361,7 +367,7 @@ int drmModeSetCursor(int fd, uint32_t crtcId, uint32_t bo_handle, uint32_t width arg.height = height; arg.handle = bo_handle; - return drmIoctl(fd, DRM_IOCTL_MODE_CURSOR, &arg); + return DRM_IOCTL(fd, DRM_IOCTL_MODE_CURSOR, &arg); } int drmModeMoveCursor(int fd, uint32_t crtcId, int x, int y) @@ -373,7 +379,7 @@ int drmModeMoveCursor(int fd, uint32_t crtcId, int x, int y) arg.x = x; arg.y = y; - return drmIoctl(fd, DRM_IOCTL_MODE_CURSOR, &arg); + return DRM_IOCTL(fd, DRM_IOCTL_MODE_CURSOR, &arg); } /* @@ -510,7 +516,7 @@ int drmModeAttachMode(int fd, uint32_t connector_id, drmModeModeInfoPtr mode_inf memcpy(&res.mode, mode_info, sizeof(struct drm_mode_modeinfo)); res.connector_id = connector_id; - return drmIoctl(fd, DRM_IOCTL_MODE_ATTACHMODE, &res); + return DRM_IOCTL(fd, DRM_IOCTL_MODE_ATTACHMODE, &res); } int drmModeDetachMode(int fd, uint32_t connector_id, drmModeModeInfoPtr mode_info) @@ -520,7 +526,7 @@ int drmModeDetachMode(int fd, uint32_t connector_id, drmModeModeInfoPtr mode_inf memcpy(&res.mode, mode_info, sizeof(struct drm_mode_modeinfo)); res.connector_id = connector_id; - return drmIoctl(fd, DRM_IOCTL_MODE_DETACHMODE, &res); + return DRM_IOCTL(fd, DRM_IOCTL_MODE_DETACHMODE, &res); } @@ -637,16 +643,12 @@ int drmModeConnectorSetProperty(int fd, uint32_t connector_id, uint32_t property uint64_t value) { struct drm_mode_connector_set_property osp; - int ret; osp.connector_id = connector_id; osp.prop_id = property_id; osp.value = value; - if ((ret = drmIoctl(fd, DRM_IOCTL_MODE_SETPROPERTY, &osp))) - return ret; - - return 0; + return DRM_IOCTL(fd, DRM_IOCTL_MODE_SETPROPERTY, &osp); } /* @@ -715,7 +717,6 @@ int drmCheckModesettingSupported(const char *busid) int drmModeCrtcGetGamma(int fd, uint32_t crtc_id, uint32_t size, uint16_t *red, uint16_t *green, uint16_t *blue) { - int ret; struct drm_mode_crtc_lut l; l.crtc_id = crtc_id; @@ -724,16 +725,12 @@ int drmModeCrtcGetGamma(int fd, uint32_t crtc_id, uint32_t size, l.green = VOID2U64(green); l.blue = VOID2U64(blue); - if ((ret = drmIoctl(fd, DRM_IOCTL_MODE_GETGAMMA, &l))) - return ret; - - return 0; + return DRM_IOCTL(fd, DRM_IOCTL_MODE_GETGAMMA, &l); } int drmModeCrtcSetGamma(int fd, uint32_t crtc_id, uint32_t size, uint16_t *red, uint16_t *green, uint16_t *blue) { - int ret; struct drm_mode_crtc_lut l; l.crtc_id = crtc_id; @@ -742,10 +739,7 @@ int drmModeCrtcSetGamma(int fd, uint32_t crtc_id, uint32_t size, l.green = VOID2U64(green); l.blue = VOID2U64(blue); - if ((ret = drmIoctl(fd, DRM_IOCTL_MODE_SETGAMMA, &l))) - return ret; - - return 0; + return DRM_IOCTL(fd, DRM_IOCTL_MODE_SETGAMMA, &l); } int drmHandleEvent(int fd, drmEventContextPtr evctx) @@ -810,5 +804,5 @@ int drmModePageFlip(int fd, uint32_t crtc_id, uint32_t fb_id, flip.flags = flags; flip.reserved = 0; - return drmIoctl(fd, DRM_IOCTL_MODE_PAGE_FLIP, &flip); + return DRM_IOCTL(fd, DRM_IOCTL_MODE_PAGE_FLIP, &flip); }