summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/ilo/ilo_blit.c
diff options
context:
space:
mode:
authorChia-I Wu <[email protected]>2013-05-17 15:54:45 +0800
committerChia-I Wu <[email protected]>2013-05-21 11:47:20 +0800
commitc44ebb4ef44422db35f985bb177482a13b4302aa (patch)
tree91416867072fd8f8ea9c3c2ed047d368e25167b3 /src/gallium/drivers/ilo/ilo_blit.c
parent731cafe7b24dbf846651264a3463821ce61148d1 (diff)
ilo: use BLT engine to copy between buffers
Emit (possibly multiple) SRC_COPY_BLT to copy between buffers of arbitrary sizes.
Diffstat (limited to 'src/gallium/drivers/ilo/ilo_blit.c')
-rw-r--r--src/gallium/drivers/ilo/ilo_blit.c143
1 files changed, 142 insertions, 1 deletions
diff --git a/src/gallium/drivers/ilo/ilo_blit.c b/src/gallium/drivers/ilo/ilo_blit.c
index 80308949c6e..d9ff711aa77 100644
--- a/src/gallium/drivers/ilo/ilo_blit.c
+++ b/src/gallium/drivers/ilo/ilo_blit.c
@@ -119,6 +119,147 @@ gen6_XY_COLOR_BLT(struct ilo_context *ilo, struct intel_bo *dst_bo,
ilo_cp_end(cp);
}
+static void
+gen6_SRC_COPY_BLT(struct ilo_context *ilo, struct intel_bo *dst_bo,
+ uint32_t dst_offset, int16_t dst_pitch,
+ uint16_t width, uint16_t height,
+ struct intel_bo *src_bo,
+ uint32_t src_offset, int16_t src_pitch,
+ uint8_t rop, int cpp, bool write_alpha, bool dir_rtl)
+{
+ const uint8_t cmd_len = 6;
+ struct ilo_cp *cp = ilo->cp;
+ uint32_t dw0, dw1;
+
+ assert(cpp == 4 || cpp == 2 || cpp == 1);
+ assert(width < gen6_max_bytes_per_scanline);
+ assert(height < gen6_max_scanlines);
+ /* offsets are naturally aligned and pitches are dword-aligned */
+ assert(dst_offset % cpp == 0 && dst_pitch % 4 == 0);
+ assert(src_offset % cpp == 0 && src_pitch % 4 == 0);
+
+#ifndef SRC_COPY_BLT_CMD
+#define SRC_COPY_BLT_CMD (CMD_2D | (0x43 << 22))
+#endif
+ dw0 = SRC_COPY_BLT_CMD | (cmd_len - 2);
+ dw1 = rop << 16 | dst_pitch;
+
+ if (dir_rtl)
+ dw1 |= 1 << 30;
+
+ switch (cpp) {
+ case 4:
+ dw0 |= XY_BLT_WRITE_RGB;
+ if (write_alpha)
+ dw0 |= XY_BLT_WRITE_ALPHA;
+
+ dw1 |= BR13_8888;
+ break;
+ case 2:
+ dw1 |= BR13_565;
+ break;
+ case 1:
+ dw1 |= BR13_8;
+ break;
+ }
+
+ ilo_cp_begin(cp, cmd_len);
+ ilo_cp_write(cp, dw0);
+ ilo_cp_write(cp, dw1);
+ ilo_cp_write(cp, height << 16 | width);
+ ilo_cp_write_bo(cp, dst_offset, dst_bo, INTEL_DOMAIN_RENDER,
+ INTEL_DOMAIN_RENDER);
+ ilo_cp_write(cp, src_pitch);
+ ilo_cp_write_bo(cp, src_offset, src_bo, INTEL_DOMAIN_RENDER, 0);
+ ilo_cp_end(cp);
+}
+
+static bool
+buf_copy_region(struct ilo_context *ilo,
+ struct ilo_buffer *dst, unsigned dst_offset,
+ struct ilo_buffer *src, unsigned src_offset,
+ unsigned size)
+{
+ const uint8_t rop = 0xcc; /* SRCCOPY */
+ unsigned offset = 0;
+ struct intel_bo *aper_check[3];
+
+ ilo_blit_own_blt_ring(ilo);
+
+ /* make room if necessary */
+ aper_check[0] = ilo->cp->bo;
+ aper_check[1] = dst->bo;
+ aper_check[2] = src->bo;
+ if (ilo->winsys->check_aperture_space(ilo->winsys, aper_check, 3))
+ ilo_cp_flush(ilo->cp);
+
+ while (size) {
+ unsigned width, height;
+ int16_t pitch;
+
+ width = size;
+ height = 1;
+ pitch = 0;
+
+ if (width > gen6_max_bytes_per_scanline) {
+ /* less than INT16_MAX and dword-aligned */
+ pitch = 32764;
+
+ width = pitch;
+ height = size / width;
+ if (height > gen6_max_scanlines)
+ height = gen6_max_scanlines;
+ }
+
+ gen6_SRC_COPY_BLT(ilo,
+ dst->bo, dst_offset + offset, pitch,
+ width, height,
+ src->bo, src_offset + offset, pitch,
+ rop, 1, true, false);
+
+ offset += pitch * height;
+ size -= width * height;
+ }
+
+ return true;
+}
+
+static void
+ilo_resource_copy_region(struct pipe_context *pipe,
+ struct pipe_resource *dst,
+ unsigned dst_level,
+ unsigned dstx, unsigned dsty, unsigned dstz,
+ struct pipe_resource *src,
+ unsigned src_level,
+ const struct pipe_box *src_box)
+{
+ bool success;
+
+ if (dst->target == PIPE_BUFFER && src->target == PIPE_BUFFER) {
+ const unsigned dst_offset = dstx;
+ const unsigned src_offset = src_box->x;
+ const unsigned size = src_box->width;
+
+ assert(dst_level == 0 && dsty == 0 && dstz == 0);
+ assert(src_level == 0 &&
+ src_box->y == 0 &&
+ src_box->z == 0 &&
+ src_box->height == 1 &&
+ src_box->depth == 1);
+
+ success = buf_copy_region(ilo_context(pipe),
+ ilo_buffer(dst), dst_offset, ilo_buffer(src), src_offset, size);
+ }
+ else {
+ success = false;
+ }
+
+ if (!success) {
+ util_resource_copy_region(pipe, dst, dst_level,
+ dstx, dsty, dstz, src, src_level, src_box);
+ }
+}
+
static bool
blitter_xy_color_blt(struct pipe_context *pipe,
struct pipe_resource *res,
@@ -331,7 +472,7 @@ ilo_blit(struct pipe_context *pipe, const struct pipe_blit_info *info)
void
ilo_init_blit_functions(struct ilo_context *ilo)
{
- ilo->base.resource_copy_region = util_resource_copy_region;
+ ilo->base.resource_copy_region = ilo_resource_copy_region;
ilo->base.blit = ilo_blit;
ilo->base.clear = ilo_clear;