diff options
Diffstat (limited to 'src/sna/sna_accel.c')
-rw-r--r-- | src/sna/sna_accel.c | 265 |
1 files changed, 155 insertions, 110 deletions
diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c index 8fa59a66..52e75c76 100644 --- a/src/sna/sna_accel.c +++ b/src/sna/sna_accel.c @@ -44,6 +44,7 @@ #include <fbpict.h> #endif #include <miline.h> +#include <shmint.h> #include <sys/time.h> #include <sys/mman.h> @@ -61,7 +62,8 @@ #define USE_INPLACE 1 #define USE_WIDE_SPANS 1 /* -1 force CPU, 1 force GPU */ #define USE_ZERO_SPANS 1 /* -1 force CPU, 1 force GPU */ -#define USE_BO_FOR_SCRATCH_PIXMAP 1 +#define USE_SHM_VMAP 0 +#define PREFER_VMAP 0 #define MIGRATE_ALL 0 @@ -302,27 +304,21 @@ 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->create & KGEM_CAN_CREATE_GPU) == 0) && - (priv->create & KGEM_CAN_CREATE_CPU)) { + if (priv->create & KGEM_CAN_CREATE_CPU) { DBG(("%s: allocating CPU buffer (%dx%d)\n", __FUNCTION__, pixmap->drawable.width, pixmap->drawable.height)); - priv->cpu_bo = kgem_create_2d(&sna->kgem, - pixmap->drawable.width, - pixmap->drawable.height, - pixmap->drawable.bitsPerPixel, - I915_TILING_NONE, - from_gpu ? 0 : CREATE_CPU_MAP | CREATE_INACTIVE); + priv->cpu_bo = kgem_create_cpu_2d(&sna->kgem, + pixmap->drawable.width, + pixmap->drawable.height, + pixmap->drawable.bitsPerPixel, + from_gpu ? 0 : CREATE_CPU_MAP | CREATE_INACTIVE); DBG(("%s: allocated CPU handle=%d\n", __FUNCTION__, priv->cpu_bo->handle)); if (priv->cpu_bo) { priv->ptr = kgem_bo_map__cpu(&sna->kgem, priv->cpu_bo); - if (priv->ptr == NULL) { - kgem_bo_destroy(&sna->kgem, priv->cpu_bo); - priv->cpu_bo = NULL; - } else - priv->stride = priv->cpu_bo->pitch; + priv->stride = priv->cpu_bo->pitch; } } @@ -349,7 +345,8 @@ static void sna_pixmap_free_cpu(struct sna *sna, struct sna_pixmap *priv) if (priv->cpu_bo) { DBG(("%s: discarding CPU buffer, handle=%d, size=%d\n", __FUNCTION__, priv->cpu_bo->handle, kgem_bo_size(priv->cpu_bo))); - + if (priv->cpu_bo->sync) + kgem_bo_sync__cpu(&sna->kgem, priv->cpu_bo); kgem_bo_destroy(&sna->kgem, priv->cpu_bo); priv->cpu_bo = NULL; } else @@ -377,14 +374,6 @@ static Bool sna_destroy_private(PixmapPtr pixmap, struct sna_pixmap *priv) if (priv->ptr) sna_pixmap_free_cpu(sna, priv); - if (priv->cpu_bo) { - if (priv->cpu_bo->vmap && kgem_bo_is_busy(priv->cpu_bo)) { - list_add_tail(&priv->list, &sna->deferred_free); - return false; - } - kgem_bo_destroy(&sna->kgem, priv->cpu_bo); - } - if (!sna->freed_pixmap && priv->header) { sna->freed_pixmap = pixmap; assert(priv->ptr == NULL); @@ -524,7 +513,6 @@ _sna_pixmap_reset(PixmapPtr pixmap) assert(pixmap->drawable.type == DRAWABLE_PIXMAP); assert(pixmap->drawable.class == 0); - assert(pixmap->drawable.id == 0); assert(pixmap->drawable.x == 0); assert(pixmap->drawable.y == 0); @@ -561,11 +549,6 @@ struct sna_pixmap *_sna_pixmap_attach(PixmapPtr pixmap) pixmap->usage_hint)); switch (pixmap->usage_hint) { - case CREATE_PIXMAP_USAGE_SCRATCH_HEADER: -#if !FAKE_CREATE_PIXMAP_USAGE_SCRATCH_HEADER - if (sna->kgem.has_vmap) - break; -#endif case CREATE_PIXMAP_USAGE_GLYPH_PICTURE: DBG(("%s: not attaching due to crazy usage: %d\n", __FUNCTION__, pixmap->usage_hint)); @@ -594,15 +577,6 @@ struct sna_pixmap *_sna_pixmap_attach(PixmapPtr pixmap) pixmap->drawable.width, pixmap->drawable.height); - if (pixmap->usage_hint == CREATE_PIXMAP_USAGE_SCRATCH_HEADER) { - priv->cpu_bo = kgem_create_map(&sna->kgem, - pixmap->devPrivate.ptr, - pixmap_size(pixmap), - 0); - if (priv->cpu_bo) - priv->cpu_bo->pitch = pixmap->devKind; - } - return priv; } @@ -630,6 +604,75 @@ create_pixmap(struct sna *sna, ScreenPtr screen, } static PixmapPtr +sna_pixmap_create_shm(ScreenPtr screen, + int width, int height, int depth, + char *addr) +{ + struct sna *sna = to_sna_from_screen(screen); + int bpp = BitsPerPixel(depth); + int pitch = PixmapBytePad(width, depth); + struct sna_pixmap *priv; + PixmapPtr pixmap; + + DBG(("%s(%d, %d, %d)\n", __FUNCTION__, + width, height, depth)); + + if (sna->freed_pixmap) { + pixmap = sna->freed_pixmap; + sna->freed_pixmap = NULL; + + pixmap->usage_hint = -1; + pixmap->refcnt = 1; + + pixmap->drawable.width = width; + pixmap->drawable.height = height; + pixmap->drawable.depth = depth; + pixmap->drawable.bitsPerPixel = bpp; + pixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER; + + DBG(("%s: serial=%ld, %dx%d\n", + __FUNCTION__, + pixmap->drawable.serialNumber, + pixmap->drawable.width, + pixmap->drawable.height)); + + priv = _sna_pixmap_reset(pixmap); + } else { + pixmap = create_pixmap(sna, screen, 0, 0, depth, -1); + if (pixmap == NullPixmap) + return NullPixmap; + + pixmap->drawable.width = width; + pixmap->drawable.height = height; + pixmap->drawable.depth = depth; + pixmap->drawable.bitsPerPixel = bpp; + + priv = __sna_pixmap_attach(sna, pixmap); + if (!priv) { + fbDestroyPixmap(pixmap); + return NullPixmap; + } + } + + priv->cpu_bo = kgem_create_map(&sna->kgem, addr, pitch*height, false); + if (priv->cpu_bo == NULL) { + free(priv); + fbDestroyPixmap(pixmap); + return GetScratchPixmapHeader(screen, width, height, depth, + bpp, pitch, addr); + } + kgem_bo_set_sync(&sna->kgem, priv->cpu_bo); + priv->cpu_bo->pitch = pitch; + + priv->header = true; + sna_damage_all(&priv->cpu_damage, width, height); + + pixmap->devKind = pitch; + pixmap->devPrivate.ptr = addr; + return pixmap; +} + +static PixmapPtr sna_pixmap_create_scratch(ScreenPtr screen, int width, int height, int depth, uint32_t tiling) @@ -723,6 +766,11 @@ static PixmapPtr sna_create_pixmap(ScreenPtr screen, DBG(("%s(%d, %d, %d, usage=%x)\n", __FUNCTION__, width, height, depth, usage)); + if ((width|height) == 0) { + usage = -1; + goto fallback; + } + if (!sna->have_render) goto fallback; @@ -733,11 +781,6 @@ static PixmapPtr sna_create_pixmap(ScreenPtr screen, goto fallback; } -#if FAKE_CREATE_PIXMAP_USAGE_SCRATCH_HEADER - if (width == 0 || height == 0) - goto fallback; -#endif - if (usage == CREATE_PIXMAP_USAGE_SCRATCH) { if (flags & KGEM_CAN_CREATE_GPU) return sna_pixmap_create_scratch(screen, @@ -919,14 +962,16 @@ _sna_pixmap_move_to_cpu(PixmapPtr pixmap, unsigned int flags) sna_damage_destroy(&priv->cpu_damage); priv->undamaged = false; list_del(&priv->list); - if (priv->cpu_bo) + if (priv->cpu_bo) { + assert(!priv->cpu_bo->sync); sna_pixmap_free_cpu(sna, priv); + } return true; } skip_inplace_map: - if (priv->cpu_bo && kgem_bo_is_busy(priv->cpu_bo)) { + if (priv->cpu_bo && !priv->cpu_bo->sync && kgem_bo_is_busy(priv->cpu_bo)) { if (priv->cpu_bo->exec == NULL) kgem_retire(&sna->kgem); @@ -941,6 +986,7 @@ skip_inplace_map: list_del(&priv->list); priv->undamaged = false; } + assert(!priv->cpu_bo->sync); sna_pixmap_free_cpu(sna, priv); } } @@ -982,7 +1028,7 @@ skip_inplace_map: } if (priv->clear) { - if (priv->cpu_bo && kgem_bo_is_busy(priv->cpu_bo)) + if (priv->cpu_bo && !priv->cpu_bo->sync && kgem_bo_is_busy(priv->cpu_bo)) sna_pixmap_free_cpu(sna, priv); sna_damage_destroy(&priv->gpu_damage); priv->undamaged = true; @@ -1282,7 +1328,7 @@ sna_drawable_move_region_to_cpu(DrawablePtr drawable, } } - if (priv->cpu_bo && !priv->cpu_bo->vmap) { + if (priv->cpu_bo && !priv->cpu_bo->sync) { if (sync_will_stall(priv->cpu_bo) && priv->cpu_bo->exec == NULL) kgem_retire(&sna->kgem); if (sync_will_stall(priv->cpu_bo)) { @@ -1372,7 +1418,7 @@ sna_drawable_move_region_to_cpu(DrawablePtr drawable, assert(pixmap_contains_damage(pixmap, priv->gpu_damage)); ok = FALSE; - if (priv->cpu_bo && sna->kgem.gen >= 60) + if (priv->cpu_bo && sna->kgem.gen >= 30) ok = sna->render.copy_boxes(sna, GXcopy, pixmap, priv->gpu_bo, 0, 0, pixmap, priv->cpu_bo, 0, 0, @@ -1910,6 +1956,9 @@ use_cpu_bo: if (priv->cpu_bo == NULL) return NULL; + if (priv->cpu_bo->sync && !kgem_bo_is_busy(priv->cpu_bo)) + return NULL; + /* Continue to use the shadow pixmap once mapped */ if (pixmap->devPrivate.ptr) { /* But only if we do not need to sync the CPU bo */ @@ -2084,6 +2133,7 @@ sna_pixmap_force_to_gpu(PixmapPtr pixmap, unsigned flags) sna_damage_destroy(&priv->cpu_damage); priv->undamaged = false; list_del(&priv->list); + assert(!priv->cpu_bo->sync); sna_pixmap_free_cpu(to_sna_from_pixmap(pixmap), priv); } @@ -2098,8 +2148,6 @@ sna_pixmap_move_to_gpu(PixmapPtr pixmap, unsigned flags) BoxPtr box; int n; - assert(pixmap->usage_hint != CREATE_PIXMAP_USAGE_SCRATCH_HEADER); - DBG(("%s(pixmap=%ld, usage=%d)\n", __FUNCTION__, pixmap->drawable.serialNumber, pixmap->usage_hint)); @@ -2209,8 +2257,10 @@ done: pixmap->drawable.height); if (DAMAGE_IS_ALL(priv->gpu_damage)) { priv->undamaged = false; - if (priv->ptr) + if (priv->ptr) { + assert(!priv->cpu_bo->sync); sna_pixmap_free_cpu(sna, priv); + } } active: return sna_pixmap_mark_active(to_sna_from_pixmap(pixmap), priv); @@ -2410,8 +2460,6 @@ sna_put_image_upload_blt(DrawablePtr drawable, GCPtr gc, RegionPtr region, PixmapPtr pixmap = get_drawable_pixmap(drawable); struct sna *sna = to_sna_from_pixmap(pixmap); struct sna_pixmap *priv = sna_pixmap(pixmap); - struct kgem_bo *src_bo; - Bool ok = FALSE; BoxPtr box; int nbox; int16_t dx, dy; @@ -2423,14 +2471,16 @@ sna_put_image_upload_blt(DrawablePtr drawable, GCPtr gc, RegionPtr region, __FUNCTION__, nbox, box->x1, box->y1, box->x2, box->y2)); + if (gc->alu != GXcopy) + return FALSE; + if (priv->gpu_bo == NULL && !sna_pixmap_create_mappable_gpu(pixmap)) return FALSE; assert(priv->gpu_bo); - if (gc->alu == GXcopy && - !priv->pinned && nbox == 1 && + if (!priv->pinned && nbox == 1 && box->x1 <= 0 && box->y1 <= 0 && box->x2 >= pixmap->drawable.width && box->y2 >= pixmap->drawable.height) @@ -2440,25 +2490,10 @@ sna_put_image_upload_blt(DrawablePtr drawable, GCPtr gc, RegionPtr region, x += dx + drawable->x; y += dy + drawable->y; - src_bo = kgem_create_map(&sna->kgem, bits, stride*h, 1); - if (src_bo) { - src_bo->pitch = stride; - ok = sna->render.copy_boxes(sna, gc->alu, - pixmap, src_bo, -x, -y, - pixmap, priv->gpu_bo, 0, 0, - box, nbox); - kgem_bo_destroy(&sna->kgem, src_bo); - } - - if (!ok && gc->alu == GXcopy) - ok = sna_write_boxes(sna, pixmap, - priv->gpu_bo, 0, 0, - bits, - stride, - -x, -y, - box, nbox); - - return ok; + return sna_write_boxes(sna, pixmap, + priv->gpu_bo, 0, 0, + bits, stride, -x, -y, + box, nbox); } static bool upload_inplace(struct sna *sna, @@ -2561,7 +2596,7 @@ sna_put_zpixmap_blt(DrawablePtr drawable, GCPtr gc, RegionPtr region, if (sync_will_stall(priv->cpu_bo) && priv->cpu_bo->exec == NULL) kgem_retire(&sna->kgem); if (sync_will_stall(priv->cpu_bo)) { - if (priv->cpu_bo->vmap) { + if (priv->cpu_bo->sync) { if (sna_put_image_upload_blt(drawable, gc, region, x, y, w, h, bits, stride)) { if (!DAMAGE_IS_ALL(priv->gpu_damage)) { @@ -2603,6 +2638,7 @@ sna_put_zpixmap_blt(DrawablePtr drawable, GCPtr gc, RegionPtr region, list_del(&priv->list); priv->undamaged = false; } + assert(!priv->cpu_bo->sync); sna_pixmap_free_cpu(sna, priv); } } @@ -3236,6 +3272,22 @@ static bool copy_use_gpu_bo(struct sna *sna, return kgem_bo_is_busy(priv->cpu_bo); } +static bool +copy_use_cpu_bo(struct sna_pixmap *priv, struct kgem_bo *dst_bo) +{ + if (priv == NULL || priv->cpu_bo == NULL) + return false; + + if (PREFER_VMAP) { + return true; + } else { + if (kgem_bo_is_busy(priv->cpu_bo) || kgem_bo_is_busy(dst_bo)) + return true; + + return !priv->cpu_bo->sync; + } +} + static void sna_copy_boxes(DrawablePtr src, DrawablePtr dst, GCPtr gc, BoxPtr box, int n, @@ -3433,7 +3485,7 @@ sna_copy_boxes(DrawablePtr src, DrawablePtr dst, GCPtr gc, RegionTranslate(®ion, -dst_dx, -dst_dy); } } - } else if (src_priv && src_priv->cpu_bo) { + } else if (copy_use_cpu_bo(src_priv, dst_priv->gpu_bo)) { if (!sna->render.copy_boxes(sna, alu, src_pixmap, src_priv->cpu_bo, src_dx, src_dy, dst_pixmap, dst_priv->gpu_bo, dst_dx, dst_dy, @@ -11445,17 +11497,30 @@ static Bool sna_change_window_attributes(WindowPtr win, unsigned long mask) } static void +sna_accel_reply_callback(CallbackListPtr *list, + pointer user_data, pointer call_data) +{ + struct sna *sna = user_data; + ReplyInfoRec *info = call_data; + + if (sna->flush || !info->startOfReply) + return; + + sna->flush = sna->kgem.flush || sna->kgem.sync; +} + +static void sna_accel_flush_callback(CallbackListPtr *list, pointer user_data, pointer call_data) { struct sna *sna = user_data; struct list preserve; - if ((sna->kgem.sync|sna->kgem.flush) == 0 && - list_is_empty(&sna->dirty_pixmaps)) + if (!sna->flush) return; - DBG(("%s\n", __FUNCTION__)); + DBG(("%s: need_sync=%d, need_flush=%d, dirty? %d\n", __FUNCTION__, + sna->kgem.sync!=NULL, sna->kgem.flush, !list_is_empty(&sna->dirty_pixmaps))); /* flush any pending damage from shadow copies to tfp clients */ list_init(&preserve); @@ -11476,35 +11541,9 @@ sna_accel_flush_callback(CallbackListPtr *list, kgem_submit(&sna->kgem); sna->kgem.flush_now = 0; - if (sna->kgem.sync) { - kgem_sync(&sna->kgem); + kgem_sync(&sna->kgem); - while (!list_is_empty(&sna->deferred_free)) { - struct sna_pixmap *priv = - list_first_entry(&sna->deferred_free, - struct sna_pixmap, - list); - list_del(&priv->list); - kgem_bo_destroy(&sna->kgem, priv->cpu_bo); - fbDestroyPixmap(priv->pixmap); - free(priv); - } - } -} - -static void sna_deferred_free(struct sna *sna) -{ - struct sna_pixmap *priv, *next; - - list_for_each_entry_safe(priv, next, &sna->deferred_free, list) { - if (kgem_bo_is_busy(priv->cpu_bo)) - continue; - - list_del(&priv->list); - kgem_bo_destroy(&sna->kgem, priv->cpu_bo); - fbDestroyPixmap(priv->pixmap); - free(priv); - } + sna->flush = false; } static struct sna_pixmap *sna_accel_scanout(struct sna *sna) @@ -11768,6 +11807,7 @@ static void sna_accel_inactive(struct sna *sna) sna_damage_destroy(&priv->cpu_damage); list_del(&priv->list); + assert(!priv->cpu_bo->sync); sna_pixmap_free_cpu(sna, priv); priv->undamaged = false; @@ -11819,10 +11859,14 @@ Bool sna_accel_pre_init(struct sna *sna) return TRUE; } +static ShmFuncs shm_funcs = { sna_pixmap_create_shm, NULL }; + Bool sna_accel_init(ScreenPtr screen, struct sna *sna) { const char *backend; + if (!AddCallback(&ReplyCallback, sna_accel_reply_callback, sna)) + return FALSE; if (!AddCallback(&FlushCallback, sna_accel_flush_callback, sna)) return FALSE; @@ -11830,7 +11874,6 @@ Bool sna_accel_init(ScreenPtr screen, struct sna *sna) screen->RealizeFont = sna_realize_font; screen->UnrealizeFont = sna_unrealize_font; - list_init(&sna->deferred_free); list_init(&sna->dirty_pixmaps); list_init(&sna->active_pixmaps); list_init(&sna->inactive_clock[0]); @@ -11866,6 +11909,9 @@ Bool sna_accel_init(ScreenPtr screen, struct sna *sna) } #endif + if (USE_SHM_VMAP && sna->kgem.has_vmap) + ShmRegisterFuncs(screen, &shm_funcs); + backend = "no"; sna->have_render = false; sna->default_tiling = I915_TILING_X; @@ -11933,6 +11979,7 @@ void sna_accel_close(struct sna *sna) sna_glyphs_close(sna); DeleteCallback(&FlushCallback, sna_accel_flush_callback, sna); + DeleteCallback(&ReplyCallback, sna_accel_reply_callback, sna); kgem_cleanup_cache(&sna->kgem); } @@ -11976,8 +12023,6 @@ void sna_accel_wakeup_handler(struct sna *sna, fd_set *ready) for (id = 0; id < NUM_TIMERS; id++) if (active & (1 << id) && FD_ISSET(sna->timer[id], ready)) sna->timer_ready |= 1 << id; - - sna_deferred_free(sna); } void sna_accel_free(struct sna *sna) |