diff options
-rw-r--r-- | configure.ac | 1 | ||||
-rw-r--r-- | src/sna/kgem.c | 114 | ||||
-rw-r--r-- | src/sna/kgem.h | 10 | ||||
-rw-r--r-- | src/sna/sna.h | 2 | ||||
-rw-r--r-- | src/sna/sna_accel.c | 111 | ||||
-rw-r--r-- | src/sna/sna_render.c | 6 | ||||
-rw-r--r-- | src/sna/sna_render_inline.h | 2 |
7 files changed, 117 insertions, 129 deletions
diff --git a/configure.ac b/configure.ac index 63beb64d..e953ae53 100644 --- a/configure.ac +++ b/configure.ac @@ -132,6 +132,7 @@ required_pixman_version=0.24 if test "x$SNA" != "xno"; then required_xorg_xserver_version=1.10 AC_DEFINE(USE_SNA, 1, [Enable SNA support]) + AC_CHECK_HEADERS([sys/sysinfo.h]) fi AC_MSG_RESULT([$SNA]) diff --git a/src/sna/kgem.c b/src/sna/kgem.c index 5ab5c83f..ca7eafae 100644 --- a/src/sna/kgem.c +++ b/src/sna/kgem.c @@ -44,6 +44,10 @@ #include <memcheck.h> #endif +#if HAVE_SYS_SYSINFO_H +#include <sys/sysinfo.h> +#endif + static struct kgem_bo * search_linear_cache(struct kgem *kgem, unsigned int num_pages, unsigned flags); @@ -498,6 +502,18 @@ agp_aperture_size(struct pci_device *dev, int gen) } static size_t +total_ram_size(void) +{ +#if HAVE_SYS_SYSINFO_H + struct sysinfo info; + if (sysinfo(&info) == 0) + return info.totalram * info.mem_unit; +#endif + + return 0; +} + +static size_t cpu_cache_size(void) { FILE *file = fopen("/proc/cpuinfo", "r"); @@ -556,6 +572,7 @@ static bool semaphores_enabled(void) void kgem_init(struct kgem *kgem, int fd, struct pci_device *dev, int gen) { struct drm_i915_gem_get_aperture aperture; + size_t totalram; unsigned int i, j; memset(kgem, 0, sizeof(*kgem)); @@ -679,6 +696,24 @@ void kgem_init(struct kgem *kgem, int fd, struct pci_device *dev, int gen) if (kgem->max_tile_size > kgem->max_gpu_size / 2) kgem->max_tile_size = kgem->max_gpu_size / 2; + totalram = total_ram_size(); + if (totalram == 0) { + DBG(("%s: total ram size unknown, assuming maximum of total aperture\n")); + totalram = kgem->aperture_total; + } + if (kgem->max_object_size > totalram / 2) + kgem->max_object_size = totalram / 2; + if (kgem->max_cpu_size > totalram / 2) + kgem->max_cpu_size = totalram / 2; + if (kgem->max_gpu_size > totalram / 4) + kgem->max_gpu_size = totalram / 4; + + kgem->large_object_size = MAX_CACHE_SIZE; + if (kgem->large_object_size > kgem->max_gpu_size) + kgem->large_object_size = kgem->max_gpu_size; + + DBG(("%s: large object thresold=%d\n", + __FUNCTION__, kgem->large_object_size)); DBG(("%s: max object size (gpu=%d, cpu=%d, tile=%d)\n", __FUNCTION__, kgem->max_gpu_size, @@ -2179,83 +2214,40 @@ done: return tiling; } -bool kgem_can_create_2d(struct kgem *kgem, - int width, int height, int depth) +unsigned kgem_can_create_2d(struct kgem *kgem, + int width, int height, int depth) { int bpp = BitsPerPixel(depth); uint32_t pitch, size; + unsigned flags = 0; if (depth < 8 || kgem->wedged) - return false; - - size = kgem_surface_size(kgem, false, false, - width, height, bpp, - I915_TILING_X, &pitch); - if (size > 0 && size <= kgem->max_object_size) - return true; - - size = kgem_surface_size(kgem, false, false, - width, height, bpp, - I915_TILING_NONE, &pitch); - if (size > 0 && size <= kgem->max_object_size) - return true; - - return false; -} - -bool kgem_can_create_cpu(struct kgem *kgem, - int width, int height, int bpp) -{ - uint32_t pitch, size; - - if (bpp < 8 || kgem->wedged) - return false; + return 0; size = kgem_surface_size(kgem, false, false, width, height, bpp, I915_TILING_NONE, &pitch); - DBG(("%s? %d, cpu size %d, max %d\n", - __FUNCTION__, - size > 0 && size <= kgem->max_cpu_size, - size, kgem->max_cpu_size)); - return size > 0 && size <= kgem->max_cpu_size; -} - -static bool _kgem_can_create_gpu(struct kgem *kgem, - int width, int height, int bpp) -{ - uint32_t pitch, size; - - if (bpp < 8 || kgem->wedged) - return false; + if (size > 0 && size <= kgem->max_cpu_size) + flags |= KGEM_CAN_CREATE_CPU | KGEM_CAN_CREATE_GPU; + if (size > kgem->large_object_size) + flags |= KGEM_CAN_CREATE_LARGE; + if (size > kgem->max_object_size) + return 0; size = kgem_surface_size(kgem, false, false, width, height, bpp, - kgem_choose_tiling(kgem, - I915_TILING_X, + kgem_choose_tiling(kgem, I915_TILING_X, width, height, bpp), &pitch); - DBG(("%s? %d, gpu size %d, max %d\n", - __FUNCTION__, - size > 0 && size < kgem->max_gpu_size, - size, kgem->max_gpu_size)); - return size > 0 && size < kgem->max_gpu_size; -} + if (size > 0 && size <= kgem->max_gpu_size) + flags |= KGEM_CAN_CREATE_GPU; + if (size > kgem->large_object_size) + flags |= KGEM_CAN_CREATE_LARGE; + if (size > kgem->max_object_size) + return 0; -#if DEBUG_KGEM -bool kgem_can_create_gpu(struct kgem *kgem, int width, int height, int bpp) -{ - bool ret = _kgem_can_create_gpu(kgem, width, height, bpp); - DBG(("%s(%dx%d, bpp=%d) = %d\n", __FUNCTION__, - width, height, bpp, ret)); - return ret; -} -#else -bool kgem_can_create_gpu(struct kgem *kgem, int width, int height, int bpp) -{ - return _kgem_can_create_gpu(kgem, width, height, bpp); + return flags; } -#endif inline int kgem_bo_fenced_size(struct kgem *kgem, struct kgem_bo *bo) { diff --git a/src/sna/kgem.h b/src/sna/kgem.h index fea2d456..87dc386f 100644 --- a/src/sna/kgem.h +++ b/src/sna/kgem.h @@ -161,7 +161,8 @@ struct kgem { uint32_t aperture_total, aperture_high, aperture_low, aperture_mappable; uint32_t aperture, aperture_fenced; uint32_t min_alignment; - uint32_t max_tile_size, max_gpu_size, max_cpu_size, max_object_size; + uint32_t max_tile_size, max_gpu_size, max_cpu_size; + uint32_t large_object_size, max_object_size; uint32_t partial_buffer_size; void (*context_switch)(struct kgem *kgem, int new_mode); @@ -201,9 +202,10 @@ struct kgem_bo *kgem_upload_source_image(struct kgem *kgem, int kgem_choose_tiling(struct kgem *kgem, int tiling, int width, int height, int bpp); -bool kgem_can_create_2d(struct kgem *kgem, int width, int height, int depth); -bool kgem_can_create_gpu(struct kgem *kgem, int width, int height, int bpp); -bool kgem_can_create_cpu(struct kgem *kgem, int width, int height, int bpp); +unsigned kgem_can_create_2d(struct kgem *kgem, int width, int height, int depth); +#define KGEM_CAN_CREATE_GPU 0x1 +#define KGEM_CAN_CREATE_CPU 0x2 +#define KGEM_CAN_CREATE_LARGE 0x4 struct kgem_bo * kgem_replace_bo(struct kgem *kgem, diff --git a/src/sna/sna.h b/src/sna/sna.h index d9ba7735..a0ea54ff 100644 --- a/src/sna/sna.h +++ b/src/sna/sna.h @@ -145,7 +145,7 @@ struct sna_pixmap { uint8_t flush :1; uint8_t clear :1; uint8_t undamaged :1; - uint8_t gpu :1; + uint8_t create :3; uint8_t header :1; }; diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c index 5d0e042a..26fd1ab9 100644 --- a/src/sna/sna_accel.c +++ b/src/sna/sna_accel.c @@ -246,11 +246,8 @@ sna_pixmap_alloc_cpu(struct sna *sna, DBG(("%s: pixmap=%ld\n", __FUNCTION__, pixmap->drawable.serialNumber)); assert(priv->stride); - if ((sna->kgem.has_cpu_bo || !priv->gpu) && - kgem_can_create_cpu(&sna->kgem, - pixmap->drawable.width, - pixmap->drawable.height, - pixmap->drawable.bitsPerPixel)) { + if ((sna->kgem.has_cpu_bo || (priv->create & KGEM_CAN_CREATE_GPU) == 0) && + (priv->create & KGEM_CAN_CREATE_CPU)) { DBG(("%s: allocating CPU buffer (%dx%d)\n", __FUNCTION__, pixmap->drawable.width, pixmap->drawable.height)); @@ -589,15 +586,7 @@ sna_pixmap_create_scratch(ScreenPtr screen, DBG(("%s(%d, %d, %d, tiling=%d)\n", __FUNCTION__, width, height, depth, tiling)); - if (depth < 8) - return create_pixmap(sna, screen, width, height, depth, - CREATE_PIXMAP_USAGE_SCRATCH); - bpp = BitsPerPixel(depth); - if (!kgem_can_create_gpu(&sna->kgem, width, height, bpp)) - return create_pixmap(sna, screen, width, height, depth, - CREATE_PIXMAP_USAGE_SCRATCH); - if (tiling == I915_TILING_Y && !sna->have_render) tiling = I915_TILING_X; @@ -672,46 +661,47 @@ static PixmapPtr sna_create_pixmap(ScreenPtr screen, { struct sna *sna = to_sna_from_screen(screen); PixmapPtr pixmap; + unsigned flags; int pad; DBG(("%s(%d, %d, %d, usage=%x)\n", __FUNCTION__, width, height, depth, usage)); - if (!kgem_can_create_2d(&sna->kgem, width, height, depth)) { + if (!sna->have_render) + goto fallback; + + flags = kgem_can_create_2d(&sna->kgem, width, height, depth); + if (flags == 0) { DBG(("%s: can not use GPU, just creating shadow\n", __FUNCTION__)); - return create_pixmap(sna, screen, width, height, depth, usage); + goto fallback; } - if (!sna->have_render) - return create_pixmap(sna, screen, - width, height, depth, - usage); - #if FAKE_CREATE_PIXMAP_USAGE_SCRATCH_HEADER if (width == 0 || height == 0) - return create_pixmap(sna, screen, width, height, depth, - CREATE_PIXMAP_USAGE_SCRATCH_HEADER); + goto fallback; #endif - if (usage == CREATE_PIXMAP_USAGE_SCRATCH) -#if USE_BO_FOR_SCRATCH_PIXMAP - return sna_pixmap_create_scratch(screen, - width, height, depth, - I915_TILING_X); -#else - return create_pixmap(sna, screen, - width, height, depth, - usage); -#endif + if (usage == CREATE_PIXMAP_USAGE_SCRATCH) { + if (flags & KGEM_CAN_CREATE_GPU) + return sna_pixmap_create_scratch(screen, + width, height, depth, + I915_TILING_X); + else + goto fallback; + } - if (usage == SNA_CREATE_SCRATCH) - return sna_pixmap_create_scratch(screen, - width, height, depth, - I915_TILING_Y); + if (usage == SNA_CREATE_SCRATCH) { + if (flags & KGEM_CAN_CREATE_GPU) + return sna_pixmap_create_scratch(screen, + width, height, depth, + I915_TILING_Y); + else + goto fallback; + } if (usage == CREATE_PIXMAP_USAGE_GLYPH_PICTURE) - return create_pixmap(sna, screen, width, height, depth, usage); + goto fallback; pad = PixmapBytePad(width, depth); if (pad * height <= 4096) { @@ -741,17 +731,17 @@ static PixmapPtr sna_create_pixmap(ScreenPtr screen, priv = __sna_pixmap_attach(sna, pixmap); if (priv == NULL) { free(pixmap); - return create_pixmap(sna, screen, - width, height, depth, usage); + goto fallback; } priv->stride = pad; - priv->gpu = kgem_can_create_gpu(&sna->kgem, - width, height, - pixmap->drawable.bitsPerPixel); + priv->create = flags; } return pixmap; + +fallback: + return create_pixmap(sna, screen, width, height, depth, usage); } static Bool sna_destroy_pixmap(PixmapPtr pixmap) @@ -844,7 +834,8 @@ _sna_pixmap_move_to_cpu(PixmapPtr pixmap, unsigned int flags) sna_damage_destroy(&priv->gpu_damage); priv->clear = false; - if (priv->gpu && pixmap_inplace(sna, pixmap, priv)) { + if (priv->create & KGEM_CAN_CREATE_GPU && + pixmap_inplace(sna, pixmap, priv)) { DBG(("%s: write inplace\n", __FUNCTION__)); if (priv->gpu_bo) { if (kgem_bo_is_busy(priv->gpu_bo) && @@ -1004,7 +995,7 @@ skip_inplace_map: priv->undamaged = true; } - if (flags & MOVE_WRITE) { + if (flags & MOVE_WRITE || priv->create & KGEM_CAN_CREATE_LARGE) { DBG(("%s: marking as damaged\n", __FUNCTION__)); sna_damage_all(&priv->cpu_damage, pixmap->drawable.width, @@ -1179,7 +1170,9 @@ sna_drawable_move_region_to_cpu(DrawablePtr drawable, if (priv->clear) return _sna_pixmap_move_to_cpu(pixmap, flags); - if (priv->gpu_bo == NULL && !priv->gpu && flags & MOVE_WRITE) + if (priv->gpu_bo == NULL && + (priv->create & KGEM_CAN_CREATE_GPU) == 0 && + flags & MOVE_WRITE) return _sna_pixmap_move_to_cpu(pixmap, flags); get_drawable_deltas(drawable, pixmap, &dx, &dy); @@ -1692,7 +1685,7 @@ sna_pixmap_move_area_to_gpu(PixmapPtr pixmap, BoxPtr box, unsigned int flags) } done: - if (!priv->pinned && priv->gpu) + if (!priv->pinned && (priv->create & KGEM_CAN_CREATE_LARGE) == 0) list_move(&priv->inactive, &sna->active_pixmaps); priv->clear = false; return true; @@ -1733,7 +1726,7 @@ sna_drawable_use_bo(DrawablePtr drawable, goto use_cpu_bo; if (priv->gpu_bo == NULL) { - if (!priv->gpu) { + if ((priv->create & KGEM_CAN_CREATE_GPU) == 0) { DBG(("%s: untiled, will not force allocation\n", __FUNCTION__)); goto use_cpu_bo; @@ -1832,7 +1825,7 @@ done: use_gpu_bo: priv->clear = false; - if (!priv->pinned && priv->gpu) + if (!priv->pinned && (priv->create & KGEM_CAN_CREATE_LARGE) == 0) list_move(&priv->inactive, &to_sna_from_pixmap(pixmap)->active_pixmaps); *damage = NULL; @@ -1883,10 +1876,6 @@ sna_pixmap_create_upload(ScreenPtr screen, DBG(("%s(%d, %d, %d)\n", __FUNCTION__, width, height, depth)); assert(width); assert(height); - if (!sna->have_render || - !kgem_can_create_gpu(&sna->kgem, width, height, bpp)) - return create_pixmap(sna, screen, width, height, depth, - CREATE_PIXMAP_USAGE_SCRATCH); if (sna->freed_pixmap) { pixmap = sna->freed_pixmap; @@ -2000,7 +1989,7 @@ sna_pixmap_force_to_gpu(PixmapPtr pixmap, unsigned flags) return NULL; /* For large bo, try to keep only a single copy around */ - if (!priv->gpu && priv->ptr) { + if (priv->create & KGEM_CAN_CREATE_LARGE && priv->ptr) { sna_damage_all(&priv->gpu_damage, pixmap->drawable.width, pixmap->drawable.height); @@ -2043,7 +2032,7 @@ sna_pixmap_move_to_gpu(PixmapPtr pixmap, unsigned flags) sna_damage_reduce(&priv->cpu_damage); DBG(("%s: CPU damage? %d\n", __FUNCTION__, priv->cpu_damage != NULL)); if (priv->gpu_bo == NULL) { - if (!wedged(sna) && priv->gpu) + if (!wedged(sna) && priv->create & KGEM_CAN_CREATE_GPU) priv->gpu_bo = kgem_create_2d(&sna->kgem, pixmap->drawable.width, @@ -2128,10 +2117,13 @@ done: sna_damage_reduce_all(&priv->gpu_damage, pixmap->drawable.width, pixmap->drawable.height); - if (DAMAGE_IS_ALL(priv->gpu_damage)) + if (DAMAGE_IS_ALL(priv->gpu_damage)) { priv->undamaged = false; + if (priv->ptr) + sna_pixmap_free_cpu(sna, priv); + } active: - if (!priv->pinned && priv->gpu) + if (!priv->pinned && (priv->create & KGEM_CAN_CREATE_LARGE) == 0) list_move(&priv->inactive, &sna->active_pixmaps); priv->clear = false; return priv; @@ -2984,7 +2976,7 @@ move_to_gpu(PixmapPtr pixmap, struct sna_pixmap *priv, if (priv->gpu_bo) return TRUE; - if (!priv->gpu) + if ((priv->create & KGEM_CAN_CREATE_GPU) == 0) return FALSE; if (priv->cpu_bo) { @@ -3241,7 +3233,8 @@ sna_copy_boxes(DrawablePtr src, DrawablePtr dst, GCPtr gc, } } else { dst_priv->clear = false; - if (!dst_priv->pinned && dst_priv->gpu) + if (!dst_priv->pinned && + (dst_priv->create & KGEM_CAN_CREATE_LARGE) == 0) list_move(&dst_priv->inactive, &sna->active_pixmaps); } @@ -11557,7 +11550,7 @@ static void sna_accel_inactive(struct sna *sna) priv = list_first_entry(&sna->inactive_clock[1], struct sna_pixmap, inactive); - assert(priv->gpu); + assert((priv->create & KGEM_CAN_CREATE_LARGE) == 0); assert(priv->gpu_bo); /* XXX Rather than discarding the GPU buffer here, we diff --git a/src/sna/sna_render.c b/src/sna/sna_render.c index 43e86424..fc6e6df4 100644 --- a/src/sna/sna_render.c +++ b/src/sna/sna_render.c @@ -332,7 +332,7 @@ use_cpu_bo(struct sna *sna, PixmapPtr pixmap, const BoxRec *box) int w = box->x2 - box->x1; int h = box->y2 - box->y1; - if (!priv->gpu) + if ((priv->create & KGEM_CAN_CREATE_GPU) == 0) goto done; if (priv->source_count*w*h >= pixmap->drawable.width * pixmap->drawable.height && @@ -380,7 +380,7 @@ move_to_gpu(PixmapPtr pixmap, const BoxRec *box) return false; upload = true; - if (!priv->gpu || + if ((priv->create & KGEM_CAN_CREATE_GPU) == 0 || kgem_choose_tiling(&to_sna_from_pixmap(pixmap)->kgem, I915_TILING_X, pixmap->drawable.width, @@ -405,7 +405,7 @@ move_to_gpu(PixmapPtr pixmap, const BoxRec *box) return FALSE; count = priv->source_count++; - if (!priv->gpu || + if ((priv->create & KGEM_CAN_CREATE_GPU) == 0 || kgem_choose_tiling(&to_sna_from_pixmap(pixmap)->kgem, I915_TILING_X, pixmap->drawable.width, diff --git a/src/sna/sna_render_inline.h b/src/sna/sna_render_inline.h index 489f2151..2805a017 100644 --- a/src/sna/sna_render_inline.h +++ b/src/sna/sna_render_inline.h @@ -102,7 +102,7 @@ too_small(DrawablePtr drawable) if (priv->cpu_bo && kgem_bo_is_busy(priv->cpu_bo)) return false; - return !priv->gpu; + return (priv->create & KGEM_CAN_CREATE_GPU) == 0; } static inline Bool |