diff options
-rw-r--r-- | src/sna/sna.h | 4 | ||||
-rw-r--r-- | src/sna/sna_accel.c | 33 | ||||
-rw-r--r-- | src/sna/sna_io.c | 196 |
3 files changed, 119 insertions, 114 deletions
diff --git a/src/sna/sna.h b/src/sna/sna.h index 7fe73597..2f14fad5 100644 --- a/src/sna/sna.h +++ b/src/sna/sna.h @@ -802,9 +802,7 @@ void sna_glyphs__shared(CARD8 op, void sna_glyph_unrealize(ScreenPtr screen, GlyphPtr glyph); void sna_glyphs_close(struct sna *sna); -void sna_read_boxes(struct sna *sna, - struct kgem_bo *src_bo, int16_t src_dx, int16_t src_dy, - PixmapPtr dst, int16_t dst_dx, int16_t dst_dy, +void sna_read_boxes(struct sna *sna, PixmapPtr dst, struct kgem_bo *src_bo, const BoxRec *box, int n); bool sna_write_boxes(struct sna *sna, PixmapPtr dst, struct kgem_bo *dst_bo, int16_t dst_dx, int16_t dst_dy, diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c index dfa33560..a51e289f 100644 --- a/src/sna/sna_accel.c +++ b/src/sna/sna_accel.c @@ -138,10 +138,7 @@ static void __sna_fallback_flush(DrawablePtr d) 0); DBG(("%s: comparing with direct read...\n", __FUNCTION__)); - sna_read_boxes(sna, - priv->gpu_bo, 0, 0, - tmp, 0, 0, - &box, 1); + sna_read_boxes(sna, tmp, priv->gpu_bo, &box, 1); src = pixmap->devPrivate.ptr; dst = tmp->devPrivate.ptr; @@ -2054,9 +2051,7 @@ skip_inplace_map: } if (!ok) { assert(has_coherent_ptr(sna_pixmap(pixmap))); - sna_read_boxes(sna, - priv->gpu_bo, 0, 0, - pixmap, 0, 0, + sna_read_boxes(sna, pixmap, priv->gpu_bo, box, n); } } @@ -2491,9 +2486,7 @@ sna_drawable_move_region_to_cpu(DrawablePtr drawable, } if (!ok) { assert(has_coherent_ptr(sna_pixmap(pixmap))); - sna_read_boxes(sna, - priv->gpu_bo, 0, 0, - pixmap, 0, 0, + sna_read_boxes(sna, pixmap, priv->gpu_bo, box, n); } } @@ -2515,9 +2508,7 @@ sna_drawable_move_region_to_cpu(DrawablePtr drawable, region->extents.y2 - region->extents.y1 == 1) { /* Often associated with synchronisation, KISS */ DBG(("%s: single pixel read\n", __FUNCTION__)); - sna_read_boxes(sna, - priv->gpu_bo, 0, 0, - pixmap, 0, 0, + sna_read_boxes(sna, pixmap, priv->gpu_bo, ®ion->extents, 1); goto done; } @@ -2542,9 +2533,7 @@ sna_drawable_move_region_to_cpu(DrawablePtr drawable, if ((flags & MOVE_WRITE) == 0 && region->extents.x2 - region->extents.x1 == 1 && region->extents.y2 - region->extents.y1 == 1) { - sna_read_boxes(sna, - priv->gpu_bo, 0, 0, - pixmap, 0, 0, + sna_read_boxes(sna, pixmap, priv->gpu_bo, ®ion->extents, 1); goto done; } @@ -2608,9 +2597,7 @@ sna_drawable_move_region_to_cpu(DrawablePtr drawable, if (!ok) { assert(has_coherent_ptr(sna_pixmap(pixmap))); - sna_read_boxes(sna, - priv->gpu_bo, 0, 0, - pixmap, 0, 0, + sna_read_boxes(sna, pixmap, priv->gpu_bo, box, n); } } @@ -2635,9 +2622,7 @@ sna_drawable_move_region_to_cpu(DrawablePtr drawable, } if (!ok) { assert(has_coherent_ptr(sna_pixmap(pixmap))); - sna_read_boxes(sna, - priv->gpu_bo, 0, 0, - pixmap, 0, 0, + sna_read_boxes(sna, pixmap, priv->gpu_bo, box, n); } @@ -2663,9 +2648,7 @@ sna_drawable_move_region_to_cpu(DrawablePtr drawable, } if (!ok) { assert(has_coherent_ptr(sna_pixmap(pixmap))); - sna_read_boxes(sna, - priv->gpu_bo, 0, 0, - pixmap, 0, 0, + sna_read_boxes(sna, pixmap, priv->gpu_bo, box, n); } diff --git a/src/sna/sna_io.c b/src/sna/sna_io.c index a4932b8d..78614622 100644 --- a/src/sna/sna_io.c +++ b/src/sna/sna_io.c @@ -53,55 +53,91 @@ static inline bool must_tile(struct sna *sna, int width, int height) upload_too_large(sna, width, height)); } -static bool bo_inplace_tiled(struct kgem *kgem, struct kgem_bo *bo, bool write) +static bool download_inplace__cpu(struct kgem *kgem, + PixmapPtr p, struct kgem_bo *bo, + const BoxRec *box, int nbox) { - if (bo->tiling != I915_TILING_X) - return false; + BoxRec extents; - return kgem_bo_can_map__cpu(kgem, bo, write); -} + switch (bo->tiling) { + case I915_TILING_X: + if (!kgem->memcpy_from_tiled_x) + return false; + case I915_TILING_NONE: + break; + default: + return false; + } -static bool download_inplace__tiled(struct kgem *kgem, struct kgem_bo *bo) -{ - if (!kgem->memcpy_from_tiled_x) + if (!kgem_bo_can_map__cpu(kgem, bo, false)) return false; - return bo_inplace_tiled(kgem, bo, false); + if (kgem->has_llc) + return true; + + extents = *box; + while (--nbox) { + ++box; + if (box->x1 < extents.x1) + extents.x1 = box->x1; + if (box->x2 > extents.x2) + extents.x2 = box->x2; + extents.y2 = box->y2; + } + + if (extents.x2 - extents.x1 == p->drawable.width && + extents.y2 - extents.y1 == p->drawable.height) + return true; + + return __kgem_bo_size(bo) <= PAGE_SIZE; } static bool -read_boxes_inplace__tiled(struct kgem *kgem, - struct kgem_bo *bo, int16_t src_dx, int16_t src_dy, - PixmapPtr pixmap, int16_t dst_dx, int16_t dst_dy, - const BoxRec *box, int n) +read_boxes_inplace__cpu(struct kgem *kgem, + PixmapPtr pixmap, struct kgem_bo *bo, + const BoxRec *box, int n) { int bpp = pixmap->drawable.bitsPerPixel; void *src, *dst = pixmap->devPrivate.ptr; int src_pitch = bo->pitch; int dst_pitch = pixmap->devKind; - assert(bo->tiling == I915_TILING_X); + if (!download_inplace__cpu(kgem, dst, bo, box, n)) + return false; + + assert(kgem_bo_can_map__cpu(kgem, bo, false)); + assert(bo->tiling != I915_TILING_Y); src = __kgem_bo_map__cpu(kgem, bo); if (src == NULL) return false; kgem_bo_sync__cpu_full(kgem, bo, 0); - do { - memcpy_from_tiled_x(kgem, src, dst, bpp, src_pitch, dst_pitch, - box->x1 + src_dx, box->y1 + src_dy, - box->x1 + dst_dx, box->y1 + dst_dy, - box->x2 - box->x1, box->y2 - box->y1); - box++; - } while (--n); + if (bo->tiling == I915_TILING_X) { + assert(kgem->memcpy_from_tiled_x); + do { + memcpy_from_tiled_x(kgem, src, dst, bpp, src_pitch, dst_pitch, + box->x1, box->y1, + box->x1, box->y1, + box->x2 - box->x1, box->y2 - box->y1); + box++; + } while (--n); + } else { + do { + memcpy_blt(src, dst, bpp, src_pitch, dst_pitch, + box->x1, box->y1, + box->x1, box->y1, + box->x2 - box->x1, box->y2 - box->y1); + box++; + } while (--n); + } __kgem_bo_unmap__cpu(kgem, bo, src); return true; } static void read_boxes_inplace(struct kgem *kgem, - struct kgem_bo *bo, int16_t src_dx, int16_t src_dy, - PixmapPtr pixmap, int16_t dst_dx, int16_t dst_dy, + PixmapPtr pixmap, struct kgem_bo *bo, const BoxRec *box, int n) { int bpp = pixmap->drawable.bitsPerPixel; @@ -109,10 +145,7 @@ static void read_boxes_inplace(struct kgem *kgem, int src_pitch = bo->pitch; int dst_pitch = pixmap->devKind; - if (download_inplace__tiled(kgem, bo) && - read_boxes_inplace__tiled(kgem, bo, src_dx, src_dy, - pixmap, dst_dx, dst_dy, - box, n)) + if (read_boxes_inplace__cpu(kgem, pixmap, bo, box, n)) return; DBG(("%s x %d, tiling=%d\n", __FUNCTION__, n, bo->tiling)); @@ -134,31 +167,36 @@ static void read_boxes_inplace(struct kgem *kgem, assert(box->x2 > box->x1); assert(box->y2 > box->y1); - assert(box->x1 + src_dx >= 0); - assert(box->y1 + src_dy >= 0); - assert(box->x2 + src_dx <= pixmap->drawable.width); - assert(box->y2 + src_dy <= pixmap->drawable.height); + assert(box->x1 >= 0); + assert(box->y1 >= 0); + assert(box->x2 <= pixmap->drawable.width); + assert(box->y2 <= pixmap->drawable.height); - assert(box->x1 + dst_dx >= 0); - assert(box->y1 + dst_dy >= 0); - assert(box->x2 + dst_dx <= pixmap->drawable.width); - assert(box->y2 + dst_dy <= pixmap->drawable.height); + assert(box->x1 >= 0); + assert(box->y1 >= 0); + assert(box->x2 <= pixmap->drawable.width); + assert(box->y2 <= pixmap->drawable.height); memcpy_blt(src, dst, bpp, src_pitch, dst_pitch, - box->x1 + src_dx, box->y1 + src_dy, - box->x1 + dst_dx, box->y1 + dst_dy, + box->x1, box->y1, + box->x1, box->y1, box->x2 - box->x1, box->y2 - box->y1); box++; } while (--n); } -static bool download_inplace(struct kgem *kgem, struct kgem_bo *bo) +static bool download_inplace(struct kgem *kgem, + PixmapPtr p, struct kgem_bo *bo, + const BoxRec *box, int nbox) { + bool cpu; + if (unlikely(kgem->wedged)) return true; - if (!kgem_bo_can_map(kgem, bo) && !download_inplace__tiled(kgem, bo)) + cpu = download_inplace__cpu(kgem, p, bo, box, nbox); + if (!cpu && !kgem_bo_can_map(kgem, bo)) return false; if (FORCE_INPLACE) @@ -167,14 +205,10 @@ static bool download_inplace(struct kgem *kgem, struct kgem_bo *bo) if (kgem->can_blt_cpu && kgem->max_cpu_size) return false; - return !__kgem_bo_is_busy(kgem, bo) || - bo->tiling == I915_TILING_NONE || - download_inplace__tiled(kgem, bo); + return !__kgem_bo_is_busy(kgem, bo) || cpu; } -void sna_read_boxes(struct sna *sna, - struct kgem_bo *src_bo, int16_t src_dx, int16_t src_dy, - PixmapPtr dst, int16_t dst_dx, int16_t dst_dy, +void sna_read_boxes(struct sna *sna, PixmapPtr dst, struct kgem_bo *src_bo, const BoxRec *box, int nbox) { struct kgem *kgem = &sna->kgem; @@ -188,20 +222,19 @@ void sna_read_boxes(struct sna *sna, int n, cmd, br13; bool can_blt; - DBG(("%s x %d, src=(handle=%d, offset=(%d,%d)), dst=(size=(%d, %d), offset=(%d,%d))\n", - __FUNCTION__, nbox, src_bo->handle, src_dx, src_dy, - dst->drawable.width, dst->drawable.height, dst_dx, dst_dy)); + DBG(("%s x %d, src=(handle=%d), dst=(size=(%d, %d)\n", + __FUNCTION__, nbox, src_bo->handle, src_dy, + dst->drawable.width, dst->drawable.height)); #ifndef NDEBUG for (n = 0; n < nbox; n++) { - if (box[n].x1 + src_dx < 0 || box[n].y1 + src_dy < 0 || - (box[n].x2 + src_dx) * dst->drawable.bitsPerPixel/8 > src_bo->pitch || - (box[n].y2 + src_dy) * src_bo->pitch > kgem_bo_size(src_bo)) + if (box[n].x1 < 0 || box[n].y1 < 0 || + box[n].x2 * dst->drawable.bitsPerPixel/8 > src_bo->pitch || + box[n].y2 * src_bo->pitch > kgem_bo_size(src_bo)) { - FatalError("source out-of-bounds box[%d]=(%d, %d), (%d, %d) + (%d, %d), pitch=%d, size=%d\n", n, + FatalError("source out-of-bounds box[%d]=(%d, %d), (%d, %d), pitch=%d, size=%d\n", n, box[n].x1, box[n].y1, box[n].x2, box[n].y2, - src_dx, src_dy, src_bo->pitch, kgem_bo_size(src_bo)); } } @@ -213,12 +246,9 @@ void sna_read_boxes(struct sna *sna, * this path. */ - if (download_inplace(kgem, src_bo)) { + if (download_inplace(kgem, dst, src_bo, box ,nbox)) { fallback: - read_boxes_inplace(kgem, - src_bo, src_dx, src_dy, - dst, dst_dx, dst_dy, - box, nbox); + read_boxes_inplace(kgem, dst, src_bo, box, nbox); return; } @@ -297,11 +327,10 @@ fallback: if (!box_intersect(c, &tile)) continue; - DBG(("%s: box(%d, %d), (%d, %d), src=(%d, %d), dst=(%d, %d)\n", + DBG(("%s: box(%d, %d), (%d, %d),, dst=(%d, %d)\n", __FUNCTION__, c->x1, c->y1, c->x2, c->y2, - src_dx, src_dy, c->x1 - tile.x1, c->y1 - tile.y1)); c++; @@ -322,7 +351,7 @@ fallback: } if (!sna->render.copy_boxes(sna, GXcopy, - dst, src_bo, src_dx, src_dy, + dst, src_bo, 0, 0, &tmp, dst_bo, -tile.x1, -tile.y1, clipped, c-clipped, COPY_LAST)) { kgem_bo_destroy(&sna->kgem, dst_bo); @@ -339,8 +368,7 @@ fallback: dst_bo->pitch, dst->devKind, c->x1 - tile.x1, c->y1 - tile.y1, - c->x1 + dst_dx, - c->y1 + dst_dy, + c->x1, c->y1, c->x2 - c->x1, c->y2 - c->y1); } @@ -362,7 +390,7 @@ fallback: goto fallback; if (!sna->render.copy_boxes(sna, GXcopy, - dst, src_bo, src_dx, src_dy, + dst, src_bo, 0, 0, &tmp, dst_bo, -extents.x1, -extents.y1, box, nbox, COPY_LAST)) { kgem_bo_destroy(&sna->kgem, dst_bo); @@ -377,8 +405,7 @@ fallback: dst_bo->pitch, dst->devKind, box[n].x1 - extents.x1, box[n].y1 - extents.y1, - box[n].x1 + dst_dx, - box[n].y1 + dst_dy, + box[n].x1, box[n].y1, box[n].x2 - box[n].x1, box[n].y2 - box[n].y1); } @@ -401,10 +428,7 @@ fallback: dst_bo = kgem_create_buffer(kgem, offset, KGEM_BUFFER_LAST, &ptr); if (!dst_bo) { - read_boxes_inplace(kgem, - src_bo, src_dx, src_dy, - dst, dst_dx, dst_dy, - box, nbox); + read_boxes_inplace(kgem, dst, src_bo, box, nbox); return; } @@ -455,15 +479,13 @@ fallback: uint32_t *b = kgem->batch + kgem->nbatch; DBG((" blt offset %x: (%d, %d) x (%d, %d), pitch=%d\n", - offset, - tmp_box[n].x1 + src_dx, - tmp_box[n].y1 + src_dy, + offset, tmp_box[n].x1, tmp_box[n].y1, width, height, pitch)); - assert(tmp_box[n].x1 + src_dx >= 0); - assert((tmp_box[n].x2 + src_dx) * dst->drawable.bitsPerPixel/8 <= src_bo->pitch); - assert(tmp_box[n].y1 + src_dy >= 0); - assert((tmp_box[n].y2 + src_dy) * src_bo->pitch <= kgem_bo_size(src_bo)); + assert(tmp_box[n].x1 >= 0); + assert(tmp_box[n].x2 * dst->drawable.bitsPerPixel/8 <= src_bo->pitch); + assert(tmp_box[n].y1 >= 0); + assert(tmp_box[n].y2 * src_bo->pitch <= kgem_bo_size(src_bo)); b[0] = cmd; b[1] = br13 | pitch; @@ -474,7 +496,7 @@ fallback: I915_GEM_DOMAIN_RENDER | KGEM_RELOC_FENCED, offset); - b[5] = (tmp_box[n].y1 + src_dy) << 16 | (tmp_box[n].x1 + src_dx); + b[5] = tmp_box[n].y1 << 16 | tmp_box[n].x1; b[6] = src_pitch; b[7] = kgem_add_reloc(kgem, kgem->nbatch + 7, src_bo, I915_GEM_DOMAIN_RENDER << 16 | @@ -505,20 +527,19 @@ fallback: DBG((" copy offset %lx [%08x...%08x...%08x]: (%d, %d) x (%d, %d), src pitch=%d, dst pitch=%d, bpp=%d\n", (long)((char *)src - (char *)ptr), *(uint32_t*)src, *(uint32_t*)(src+pitch*height/2 + pitch/2 - 4), *(uint32_t*)(src+pitch*height - 4), - box->x1 + dst_dx, - box->y1 + dst_dy, + box->x1, box->y1, width, height, pitch, dst->devKind, cpp*8)); - assert(box->x1 + dst_dx >= 0); - assert(box->x2 + dst_dx <= dst->drawable.width); - assert(box->y1 + dst_dy >= 0); - assert(box->y2 + dst_dy <= dst->drawable.height); + assert(box->x1 >= 0); + assert(box->x2 <= dst->drawable.width); + assert(box->y1 >= 0); + assert(box->y2 <= dst->drawable.height); memcpy_blt(src, dst->devPrivate.ptr, cpp*8, pitch, dst->devKind, 0, 0, - box->x1 + dst_dx, box->y1 + dst_dy, + box->x1, box->y1, width, height); box++; @@ -534,7 +555,10 @@ static bool upload_inplace__tiled(struct kgem *kgem, struct kgem_bo *bo) if (!kgem->memcpy_to_tiled_x) return false; - return bo_inplace_tiled(kgem, bo, true); + if (bo->tiling != I915_TILING_X) + return false; + + return kgem_bo_can_map__cpu(kgem, bo, true); } static bool |