diff options
author | Thomas Hellstrom <thomas-at-tungstengraphics-dot-com> | 2007-02-09 16:36:53 +0100 |
---|---|---|
committer | Thomas Hellstrom <thomas-at-tungstengraphics-dot-com> | 2007-02-09 16:36:53 +0100 |
commit | 53aee3122a1821b8ca24ed2bc5c1940cb0f2ff8e (patch) | |
tree | 66b77fadcebb1da07bd7444edfc256b0ad3261df | |
parent | 57df3980724d3da446c4576b3fadcd89c5da414e (diff) |
I915 accelerated blit copy functional.
Fixed - to System memory copies are implemented by
flipping in a cache-coherent TTM,
blitting to it, and then flipping it out.
-rw-r--r-- | linux-core/drm_bo_move.c | 4 | ||||
-rw-r--r-- | linux-core/drm_mm.c | 1 | ||||
-rw-r--r-- | linux-core/drm_ttm.c | 1 | ||||
-rw-r--r-- | linux-core/i915_buffer.c | 82 | ||||
-rw-r--r-- | linux-core/i915_drv.c | 2 | ||||
-rw-r--r-- | shared-core/i915_drv.h | 4 |
6 files changed, 77 insertions, 17 deletions
diff --git a/linux-core/drm_bo_move.c b/linux-core/drm_bo_move.c index e1340205..d712a70f 100644 --- a/linux-core/drm_bo_move.c +++ b/linux-core/drm_bo_move.c @@ -333,8 +333,10 @@ int drm_bo_move_accel_cleanup(drm_buffer_object_t *bo, if (evict) { ret = drm_bo_wait(bo, 0, 1, 0); - if (ret) + if (ret) { + DRM_ERROR("Wait failure\n"); return ret; + } if (old_mem->mm_node) { mutex_lock(&dev->struct_mutex); drm_mm_put_block(old_mem->mm_node); diff --git a/linux-core/drm_mm.c b/linux-core/drm_mm.c index 5889ee4d..634a1782 100644 --- a/linux-core/drm_mm.c +++ b/linux-core/drm_mm.c @@ -217,6 +217,7 @@ void drm_mm_put_block(drm_mm_node_t * cur) drm_ctl_free(cur, sizeof(*cur), DRM_MEM_MM); } } +EXPORT_SYMBOL(drm_mm_put_block); drm_mm_node_t *drm_mm_search_free(const drm_mm_t * mm, unsigned long size, diff --git a/linux-core/drm_ttm.c b/linux-core/drm_ttm.c index fa55a8b4..8cd961d7 100644 --- a/linux-core/drm_ttm.c +++ b/linux-core/drm_ttm.c @@ -344,3 +344,4 @@ int drm_bind_ttm(drm_ttm_t * ttm, int cached, unsigned long aper_offset) return 0; } +EXPORT_SYMBOL(drm_bind_ttm); diff --git a/linux-core/i915_buffer.c b/linux-core/i915_buffer.c index 41f05b78..70ba9a67 100644 --- a/linux-core/i915_buffer.c +++ b/linux-core/i915_buffer.c @@ -132,37 +132,28 @@ static void i915_emit_copy_blit(drm_device_t *dev, if (!dev_priv) return; - if (direction) { - stride = -stride; - src_offset += (pages - 1) << PAGE_SHIFT; - dst_offset += (pages - 1) << PAGE_SHIFT; - } - + i915_kernel_lost_context(dev); while(pages > 0) { cur_pages = pages; if (cur_pages > 2048) cur_pages = 2048; pages -= cur_pages; - BEGIN_LP_RING(8); - OUT_RING(XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA | + BEGIN_LP_RING(6); + OUT_RING(SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA | XY_SRC_COPY_BLT_WRITE_RGB); OUT_RING((stride & 0xffff) | ( 0xcc << 16) | (1 << 24) | - (1 << 25)); - OUT_RING(0); - OUT_RING((cur_pages << 16) | (PAGE_SIZE >> 2)); + (1 << 25) | (direction ? (1 << 30) : 0)); + OUT_RING((cur_pages << 16) | PAGE_SIZE); OUT_RING(dst_offset); - OUT_RING(0); OUT_RING(stride & 0xffff); OUT_RING(src_offset); ADVANCE_LP_RING(); - dst_offset += (cur_pages << PAGE_SHIFT)*(direction ? -1 : 1); - src_offset += (cur_pages << PAGE_SHIFT)*(direction ? -1 : 1); } return; } -static int drm_bo_move_blit(drm_buffer_object_t *bo, +static int i915_move_blit(drm_buffer_object_t *bo, int evict, int no_wait, drm_bo_mem_reg_t *new_mem) @@ -191,5 +182,66 @@ static int drm_bo_move_blit(drm_buffer_object_t *bo, new_mem); } +/* + * Flip destination ttm into cached-coherent AGP, + * then blit and subsequently move out again. + */ + + +static int i915_move_flip(drm_buffer_object_t *bo, + int evict, + int no_wait, + drm_bo_mem_reg_t *new_mem) +{ + drm_device_t *dev = bo->dev; + drm_bo_mem_reg_t tmp_mem; + int ret; + + tmp_mem = *new_mem; + tmp_mem.mm_node = NULL; + tmp_mem.mask = DRM_BO_FLAG_MEM_TT | + DRM_BO_FLAG_CACHED | + DRM_BO_FLAG_FORCE_CACHING; + + ret = drm_bo_mem_space(dev, &tmp_mem, no_wait); + if (ret) + return ret; + ret = drm_bind_ttm(bo->ttm, 1, tmp_mem.mm_node->start); + if (ret) + goto out_cleanup; + ret = i915_move_blit(bo, 1, no_wait, &tmp_mem); + if (ret) + goto out_cleanup; + + ret = drm_bo_move_ttm(bo, evict, no_wait, new_mem); +out_cleanup: + if (tmp_mem.mm_node) { + mutex_lock(&dev->struct_mutex); + drm_mm_put_block(tmp_mem.mm_node); + tmp_mem.mm_node = NULL; + mutex_unlock(&dev->struct_mutex); + } + return ret; +} + + +int i915_move(drm_buffer_object_t *bo, + int evict, + int no_wait, + drm_bo_mem_reg_t *new_mem) +{ + drm_bo_mem_reg_t *old_mem = &bo->mem; + + if (old_mem->mem_type == DRM_BO_MEM_LOCAL) + return drm_bo_move_memcpy(bo, evict, no_wait, new_mem); + if (new_mem->mem_type == DRM_BO_MEM_LOCAL) { + if (i915_move_flip(bo, evict, no_wait, new_mem)) + return drm_bo_move_memcpy(bo, evict, no_wait, new_mem); + } else { + if (i915_move_blit(bo, evict, no_wait, new_mem)) + return drm_bo_move_memcpy(bo, evict, no_wait, new_mem); + } + return 0; +} diff --git a/linux-core/i915_drv.c b/linux-core/i915_drv.c index 19b63b7f..848ffa78 100644 --- a/linux-core/i915_drv.c +++ b/linux-core/i915_drv.c @@ -64,7 +64,7 @@ static drm_bo_driver_t i915_bo_driver = { .invalidate_caches = i915_invalidate_caches, .init_mem_type = i915_init_mem_type, .evict_flags = i915_evict_flags, - .move = NULL, + .move = i915_move, }; #endif diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h index 55c8cf57..ffc9d431 100644 --- a/shared-core/i915_drv.h +++ b/shared-core/i915_drv.h @@ -192,6 +192,9 @@ extern int i915_invalidate_caches(drm_device_t *dev, uint32_t buffer_flags); extern int i915_init_mem_type(drm_device_t *dev, uint32_t type, drm_mem_type_manager_t *man); extern uint32_t i915_evict_flags(drm_device_t *dev, uint32_t type); +extern int i915_move(drm_buffer_object_t *bo, int evict, + int no_wait, drm_bo_mem_reg_t *new_mem); + #endif #define I915_READ(reg) DRM_READ32(dev_priv->mmio_map, (reg)) @@ -329,6 +332,7 @@ extern int i915_wait_ring(drm_device_t * dev, int n, const char *caller); #define GFX_OP_DRAWRECT_INFO_I965 ((0x7900<<16)|0x2) +#define SRC_COPY_BLT_CMD ((2<<29)|(0x43<<22)|4) #define XY_SRC_COPY_BLT_CMD ((2<<29)|(0x53<<22)|6) #define XY_SRC_COPY_BLT_WRITE_ALPHA (1<<21) #define XY_SRC_COPY_BLT_WRITE_RGB (1<<20) |