From 3812dfce175eeaef7f41632d2df6a0d88c0ae19b Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 16 Oct 2014 07:46:26 +0100 Subject: [PATCH] sna: Replace GPU render operations with CPU callbacks after wedged If we find the GPU is wedged, replace some of the lowlevel render operations with CPU equivalents to simplify some fallbacks that still need to operate on GPU bo (such as copying DRI buffers). References: https://bugs.freedesktop.org/show_bug.cgi?id=85058 Signed-off-by: Chris Wilson --- src/sna/kgem.c | 13 +++-- src/sna/sna_dri2.c | 122 +++++++++---------------------------------- src/sna/sna_render.c | 78 +++++++++++++++++++++++++++ src/sna/sna_render.h | 7 +++ 4 files changed, 119 insertions(+), 101 deletions(-) diff --git a/src/sna/kgem.c b/src/sna/kgem.c index a6aa2757..234d1d06 100644 --- a/src/sna/kgem.c +++ b/src/sna/kgem.c @@ -282,6 +282,13 @@ static void assert_bo_retired(struct kgem_bo *bo) #define assert_bo_retired(bo) #endif +static void +__kgem_set_wedged(struct kgem *kgem) +{ + kgem->wedged = true; + sna_render_mark_wedged(container_of(kgem, struct sna, kgem)); +} + static void kgem_sna_reset(struct kgem *kgem) { struct sna *sna = container_of(kgem, struct sna, kgem); @@ -3343,7 +3350,7 @@ void _kgem_submit(struct kgem *kgem) if (!kgem->wedged) { xf86DrvMsg(kgem_get_screen_index(kgem), X_ERROR, "Failed to submit rendering commands, disabling acceleration.\n"); - kgem->wedged = true; + __kgem_set_wedged(kgem); } #if !NDEBUG @@ -3451,8 +3458,7 @@ void kgem_throttle(struct kgem *kgem) if (kgem->wedged) return; - kgem->wedged = __kgem_throttle(kgem, true); - if (kgem->wedged) { + if (__kgem_throttle(kgem, true)) { static int once; char path[128]; @@ -3465,6 +3471,7 @@ void kgem_throttle(struct kgem *kgem) once = 1; } + __kgem_set_wedged(kgem); kgem->need_throttle = false; } } diff --git a/src/sna/sna_dri2.c b/src/sna/sna_dri2.c index 04ba786e..784caee8 100644 --- a/src/sna/sna_dri2.c +++ b/src/sna/sna_dri2.c @@ -862,74 +862,6 @@ static void sna_dri2_select_mode(struct sna *sna, struct kgem_bo *dst, struct kg _kgem_set_mode(&sna->kgem, mode); } -static bool can_copy_cpu(struct sna *sna, - struct kgem_bo *src, - struct kgem_bo *dst) -{ - if (src->tiling != dst->tiling) - return false; - - if (src->pitch != dst->pitch) - return false; - - if (!kgem_bo_can_map__cpu(&sna->kgem, src, false)) - return false; - - if (!kgem_bo_can_map__cpu(&sna->kgem, dst, true)) - return false; - - DBG(("%s -- yes, src handle=%d, dst handle=%d\n", __FUNCTION__, src->handle, dst->handle)); - return true; -} - -static void -sna_dri2_copy_fallback(struct sna *sna, - const DrawableRec *draw, - struct kgem_bo *src_bo, int sx, int sy, - struct kgem_bo *dst_bo, int dx, int dy, - const BoxRec *box, int n) -{ - void *dst, *src; - bool clipped; - - clipped = (n > 1 || - box->x1 + sx > 0 || - box->y1 + sy > 0 || - box->x2 + sx < draw->width || - box->y2 + sy < draw->height); - - dst = src = NULL; - if (!clipped && can_copy_cpu(sna, src_bo, dst_bo)) { - dst = kgem_bo_map__cpu(&sna->kgem, dst_bo); - src = kgem_bo_map__cpu(&sna->kgem, src_bo); - } - - if (dst == NULL || src == NULL) { - dst = kgem_bo_map__gtt(&sna->kgem, dst_bo); - src = kgem_bo_map__gtt(&sna->kgem, src_bo); - if (dst == NULL || src == NULL) - return; - } else { - kgem_bo_sync__cpu_full(&sna->kgem, dst_bo, true); - kgem_bo_sync__cpu_full(&sna->kgem, src_bo, false); - } - - DBG(("%s: src(%d, %d), dst(%d, %d) x %d\n", - __FUNCTION__, sx, sy, dx, dy, n)); - - if (sigtrap_get() == 0) { - do { - memcpy_blt(src, dst, draw->bitsPerPixel, - src_bo->pitch, dst_bo->pitch, - box->x1 + sx, box->y1 + sy, - box->x1 + dx, box->y1 + dy, - box->x2 - box->x1, box->y2 - box->y1); - box++; - } while (--n); - sigtrap_put(); - } -} - static bool is_front(int attachment) { return attachment == DRI2BufferFrontLeft; @@ -950,6 +882,7 @@ __sna_dri2_copy_region(struct sna *sna, DrawablePtr draw, RegionPtr region, struct kgem_bo *dst_bo; const BoxRec *boxes; int16_t dx, dy, sx, sy; + unsigned flags; int n; /* To hide a stale DRI2Buffer, one may choose to substitute @@ -1071,7 +1004,6 @@ __sna_dri2_copy_region(struct sna *sna, DrawablePtr draw, RegionPtr region, assert(dst_bo->refcnt); if (is_front(dst->attachment)) { struct sna_pixmap *priv; - unsigned int flags; flags = MOVE_WRITE | __MOVE_FORCE; if (clip.data) @@ -1135,38 +1067,32 @@ __sna_dri2_copy_region(struct sna *sna, DrawablePtr draw, RegionPtr region, } DamageRegionAppend(&pixmap->drawable, region); - if (wedged(sna)) { -fallback: - sna_dri2_copy_fallback(sna, src_draw, - src_bo, sx, sy, - dst_bo, dx, dy, - boxes, n); - } else { - unsigned flags; - DBG(("%s: copying [(%d, %d), (%d, %d)]x%d src=(%d, %d), dst=(%d, %d)\n", - __FUNCTION__, - boxes[0].x1, boxes[0].y1, - boxes[0].x2, boxes[0].y2, - n, sx, sy, dx, dy)); + DBG(("%s: copying [(%d, %d), (%d, %d)]x%d src=(%d, %d), dst=(%d, %d)\n", + __FUNCTION__, + boxes[0].x1, boxes[0].y1, + boxes[0].x2, boxes[0].y2, + n, sx, sy, dx, dy)); - flags = COPY_LAST; - if (sync) - flags |= COPY_SYNC; - if (!sna->render.copy_boxes(sna, GXcopy, - src_draw, src_bo, sx, sy, - dst_draw, dst_bo, dx, dy, - boxes, n, flags)) - goto fallback; + flags = COPY_LAST; + if (sync) + flags |= COPY_SYNC; + if (!sna->render.copy_boxes(sna, GXcopy, + src_draw, src_bo, sx, sy, + dst_draw, dst_bo, dx, dy, + boxes, n, flags)) + memcpy_copy_boxes(sna, GXcopy, + src_draw, src_bo, sx, sy, + dst_draw, dst_bo, dx, dy, + boxes, n, flags); - DBG(("%s: flushing? %d\n", __FUNCTION__, sync)); - if (sync) { /* STAT! */ - struct kgem_request *rq = sna->kgem.next_request; - kgem_submit(&sna->kgem); - if (rq->bo) { - bo = ref(rq->bo); - DBG(("%s: recording sync fence handle=%d\n", __FUNCTION__, bo->handle)); - } + DBG(("%s: flushing? %d\n", __FUNCTION__, sync)); + if (sync) { /* STAT! */ + struct kgem_request *rq = sna->kgem.next_request; + kgem_submit(&sna->kgem); + if (rq->bo) { + bo = ref(rq->bo); + DBG(("%s: recording sync fence handle=%d\n", __FUNCTION__, bo->handle)); } } diff --git a/src/sna/sna_render.c b/src/sna/sna_render.c index 8cc63a0d..22bc4910 100644 --- a/src/sna/sna_render.c +++ b/src/sna/sna_render.c @@ -2297,3 +2297,81 @@ cleanup_boxes: return ret; } + +static bool can_copy_cpu(struct sna *sna, + struct kgem_bo *src, + struct kgem_bo *dst) +{ + if (src->tiling != dst->tiling) + return false; + + if (src->pitch != dst->pitch) + return false; + + if (!kgem_bo_can_map__cpu(&sna->kgem, src, false)) + return false; + + if (!kgem_bo_can_map__cpu(&sna->kgem, dst, true)) + return false; + + DBG(("%s -- yes, src handle=%d, dst handle=%d\n", __FUNCTION__, src->handle, dst->handle)); + return true; +} + +bool +memcpy_copy_boxes(struct sna *sna, uint8_t op, + const DrawableRec *src_draw, struct kgem_bo *src_bo, int16_t sx, int16_t sy, + const DrawableRec *dst_draw, struct kgem_bo *dst_bo, int16_t dx, int16_t dy, + const BoxRec *box, int n, unsigned flags) +{ + void *dst, *src; + bool clipped; + + if (op != GXcopy) + return false; + + clipped = (n > 1 || + box->x1 + dx > 0 || + box->y1 + dy > 0 || + box->x2 + dx < dst_draw->width || + box->y2 + dy < dst_draw->height); + + dst = src = NULL; + if (!clipped && can_copy_cpu(sna, src_bo, dst_bo)) { + dst = kgem_bo_map__cpu(&sna->kgem, dst_bo); + src = kgem_bo_map__cpu(&sna->kgem, src_bo); + } + + if (dst == NULL || src == NULL) { + dst = kgem_bo_map__gtt(&sna->kgem, dst_bo); + src = kgem_bo_map__gtt(&sna->kgem, src_bo); + if (dst == NULL || src == NULL) + return false; + } else { + kgem_bo_sync__cpu_full(&sna->kgem, dst_bo, true); + kgem_bo_sync__cpu_full(&sna->kgem, src_bo, false); + } + + DBG(("%s: src(%d, %d), dst(%d, %d) x %d\n", + __FUNCTION__, sx, sy, dx, dy, n)); + + if (sigtrap_get() == 0) { + do { + memcpy_blt(src, dst, dst_draw->bitsPerPixel, + src_bo->pitch, dst_bo->pitch, + box->x1 + sx, box->y1 + sy, + box->x1 + dx, box->y1 + dy, + box->x2 - box->x1, box->y2 - box->y1); + box++; + } while (--n); + sigtrap_put(); + } + + return true; +} + +void +sna_render_mark_wedged(struct sna *sna) +{ + sna->render.copy_boxes = memcpy_copy_boxes; +} diff --git a/src/sna/sna_render.h b/src/sna/sna_render.h index 8b839de0..823b86cc 100644 --- a/src/sna/sna_render.h +++ b/src/sna/sna_render.h @@ -620,6 +620,8 @@ const char *gen6_render_init(struct sna *sna, const char *backend); const char *gen7_render_init(struct sna *sna, const char *backend); const char *gen8_render_init(struct sna *sna, const char *backend); +void sna_render_mark_wedged(struct sna *sna); + bool sna_tiling_composite(uint32_t op, PicturePtr src, PicturePtr mask, @@ -707,6 +709,11 @@ bool sna_blt_copy_boxes_fallback(struct sna *sna, uint8_t alu, const DrawableRec *dst, struct kgem_bo *dst_bo, int16_t dst_dx, int16_t dst_dy, const BoxRec *box, int nbox); +bool memcpy_copy_boxes(struct sna *sna, uint8_t op, + const DrawableRec *src_draw, struct kgem_bo *src_bo, int16_t sx, int16_t sy, + const DrawableRec *dst_draw, struct kgem_bo *dst_bo, int16_t dx, int16_t dy, + const BoxRec *box, int n, unsigned flags); + bool _sna_get_pixel_from_rgba(uint32_t *pixel, uint16_t red, uint16_t green,