Exemplo n.º 1
0
static uint32_t r300_depth_clear_value(enum pipe_format format,
                                       double depth, unsigned stencil)
{
    switch (format) {
        case PIPE_FORMAT_Z16_UNORM:
        case PIPE_FORMAT_X8Z24_UNORM:
            return util_pack_z(format, depth);

        case PIPE_FORMAT_S8_UINT_Z24_UNORM:
            return util_pack_z_stencil(format, depth, stencil);

        default:
            assert(0);
            return 0;
    }
}
Exemplo n.º 2
0
/**
 * Clear the given buffers to the specified values.
 * No masking, no scissor (clear entire buffer).
 */
void
softpipe_clear(struct pipe_context *pipe, unsigned buffers, const float *rgba,
               double depth, unsigned stencil)
{
   struct softpipe_context *softpipe = softpipe_context(pipe);
   unsigned cv;
   uint i;

   if (softpipe->no_rast)
      return;

#if 0
   softpipe_update_derived(softpipe); /* not needed?? */
#endif

   if (buffers & PIPE_CLEAR_COLOR) {
      for (i = 0; i < softpipe->framebuffer.nr_cbufs; i++) {
         struct pipe_surface *ps = softpipe->framebuffer.cbufs[i];

         util_pack_color(rgba, ps->format, &cv);
         sp_tile_cache_clear(softpipe->cbuf_cache[i], rgba, cv);

#if !TILE_CLEAR_OPTIMIZATION
         /* non-cached surface */
         pipe->surface_fill(pipe, ps, 0, 0, ps->width, ps->height, cv);
#endif
      }
   }

   if (buffers & PIPE_CLEAR_DEPTHSTENCIL) {
      static const float zero[4] = { 0.0F, 0.0F, 0.0F, 0.0F };
      struct pipe_surface *ps = softpipe->framebuffer.zsbuf;

      cv = util_pack_z_stencil(ps->format, depth, stencil);
      sp_tile_cache_clear(softpipe->zsbuf_cache, zero, cv);

#if !TILE_CLEAR_OPTIMIZATION
      /* non-cached surface */
      pipe->surface_fill(pipe, ps, 0, 0, ps->width, ps->height, cv);
#endif
   }

   softpipe->dirty_render_cache = TRUE;
}
Exemplo n.º 3
0
static void
i915_clear_depth_stencil_blitter(struct pipe_context *pipe,
                                 struct pipe_surface *dst,
                                 unsigned clear_flags,
                                 double depth,
                                 unsigned stencil,
                                 unsigned dstx, unsigned dsty,
                                 unsigned width, unsigned height,
                                 bool render_condition_enabled)
{
   struct i915_texture *tex = i915_texture(dst->texture);
   struct pipe_resource *pt = &tex->b.b;
   unsigned packedds;
   unsigned mask = 0;
   unsigned offset = i915_texture_offset(tex, dst->u.tex.level, dst->u.tex.first_layer);

   assert(util_format_get_blockwidth(pt->format) == 1);
   assert(util_format_get_blockheight(pt->format) == 1);

   packedds = util_pack_z_stencil(dst->format, depth, stencil);

   if (clear_flags & PIPE_CLEAR_DEPTH)
      mask |= XY_COLOR_BLT_WRITE_RGB;
   /* XXX presumably this does read-modify-write
      (otherwise this won't work anyway). Hence will only want to
      do it if really have stencil and it isn't cleared */
   if ((clear_flags & PIPE_CLEAR_STENCIL) ||
       (dst->format != PIPE_FORMAT_Z24_UNORM_S8_UINT))
      mask |= XY_COLOR_BLT_WRITE_ALPHA;

   i915_fill_blit( i915_context(pipe),
                   util_format_get_blocksize(pt->format),
                   mask,
                   (unsigned short) tex->stride,
                   tex->buffer, offset,
                   (short) dstx, (short) dsty,
                   (short) width, (short) height,
                   packedds );
}
Exemplo n.º 4
0
/**
 * Clear the given buffers to the specified values.
 * No masking, no scissor (clear entire buffer).
 */
void
softpipe_clear(struct pipe_context *pipe, unsigned buffers, const float *rgba,
               double depth, unsigned stencil)
{
   struct softpipe_context *softpipe = softpipe_context(pipe);
   union util_color uc;
   unsigned cv;
   uint i;

   if (softpipe->no_rast)
      return;

   if (!softpipe_check_render_cond(softpipe))
      return;

#if 0
   softpipe_update_derived(softpipe, PIPE_PRIM_TRIANGLES); /* not needed?? */
#endif

   if (buffers & PIPE_CLEAR_COLOR) {
      for (i = 0; i < softpipe->framebuffer.nr_cbufs; i++) {
         struct pipe_surface *ps = softpipe->framebuffer.cbufs[i];

         util_pack_color(rgba, ps->format, &uc);
         sp_tile_cache_clear(softpipe->cbuf_cache[i], rgba, uc.ui);
      }
   }

   if (buffers & PIPE_CLEAR_DEPTHSTENCIL) {
      static const float zero[4] = { 0.0F, 0.0F, 0.0F, 0.0F };
      struct pipe_surface *ps = softpipe->framebuffer.zsbuf;

      cv = util_pack_z_stencil(ps->format, depth, stencil);
      sp_tile_cache_clear(softpipe->zsbuf_cache, zero, cv);
   }

   softpipe->dirty_render_cache = TRUE;
}
Exemplo n.º 5
0
static bool
fd6_clear(struct fd_context *ctx, unsigned buffers,
		const union pipe_color_union *color, double depth, unsigned stencil)
{
	struct pipe_framebuffer_state *pfb = &ctx->batch->framebuffer;
	struct pipe_scissor_state *scissor = fd_context_get_scissor(ctx);
	struct fd_ringbuffer *ring = ctx->batch->draw;

	if ((buffers & (PIPE_CLEAR_DEPTH | PIPE_CLEAR_STENCIL)) &&
			is_z32(pfb->zsbuf->format))
		return false;

	fd6_emit_render_cntl(ctx, true, false);

	OUT_PKT4(ring, REG_A6XX_RB_BLIT_SCISSOR_TL, 2);
	OUT_RING(ring, A6XX_RB_BLIT_SCISSOR_TL_X(scissor->minx) |
			 A6XX_RB_BLIT_SCISSOR_TL_Y(scissor->miny));
	OUT_RING(ring, A6XX_RB_BLIT_SCISSOR_BR_X(scissor->maxx - 1) |
			 A6XX_RB_BLIT_SCISSOR_BR_Y(scissor->maxy - 1));

	if (buffers & PIPE_CLEAR_COLOR) {
		for (int i = 0; i < pfb->nr_cbufs; i++) {
			union util_color uc = {0};

			if (!pfb->cbufs[i])
				continue;

			if (!(buffers & (PIPE_CLEAR_COLOR0 << i)))
				continue;

			enum pipe_format pfmt = pfb->cbufs[i]->format;

			// XXX I think RB_CLEAR_COLOR_DWn wants to take into account SWAP??
			union pipe_color_union swapped;
			switch (fd6_pipe2swap(pfmt)) {
			case WZYX:
				swapped.ui[0] = color->ui[0];
				swapped.ui[1] = color->ui[1];
				swapped.ui[2] = color->ui[2];
				swapped.ui[3] = color->ui[3];
				break;
			case WXYZ:
				swapped.ui[2] = color->ui[0];
				swapped.ui[1] = color->ui[1];
				swapped.ui[0] = color->ui[2];
				swapped.ui[3] = color->ui[3];
				break;
			case ZYXW:
				swapped.ui[3] = color->ui[0];
				swapped.ui[0] = color->ui[1];
				swapped.ui[1] = color->ui[2];
				swapped.ui[2] = color->ui[3];
				break;
			case XYZW:
				swapped.ui[3] = color->ui[0];
				swapped.ui[2] = color->ui[1];
				swapped.ui[1] = color->ui[2];
				swapped.ui[0] = color->ui[3];
				break;
			}

			if (util_format_is_pure_uint(pfmt)) {
				util_format_write_4ui(pfmt, swapped.ui, 0, &uc, 0, 0, 0, 1, 1);
			} else if (util_format_is_pure_sint(pfmt)) {
				util_format_write_4i(pfmt, swapped.i, 0, &uc, 0, 0, 0, 1, 1);
			} else {
				util_pack_color(swapped.f, pfmt, &uc);
			}

			OUT_PKT4(ring, REG_A6XX_RB_BLIT_DST_INFO, 1);
			OUT_RING(ring, A6XX_RB_BLIT_DST_INFO_TILE_MODE(TILE6_LINEAR) |
				A6XX_RB_BLIT_DST_INFO_COLOR_FORMAT(fd6_pipe2color(pfmt)));

			OUT_PKT4(ring, REG_A6XX_RB_BLIT_INFO, 1);
			OUT_RING(ring, A6XX_RB_BLIT_INFO_GMEM |
				A6XX_RB_BLIT_INFO_CLEAR_MASK(0xf));

			OUT_PKT4(ring, REG_A6XX_RB_BLIT_BASE_GMEM, 1);
			OUT_RINGP(ring, i, &ctx->batch->gmem_patches);

			OUT_PKT4(ring, REG_A6XX_RB_UNKNOWN_88D0, 1);
			OUT_RING(ring, 0);

			OUT_PKT4(ring, REG_A6XX_RB_BLIT_CLEAR_COLOR_DW0, 4);
			OUT_RING(ring, uc.ui[0]);
			OUT_RING(ring, uc.ui[1]);
			OUT_RING(ring, uc.ui[2]);
			OUT_RING(ring, uc.ui[3]);

			fd6_emit_blit(ctx->batch, ring);
		}
	}

	if (pfb->zsbuf && (buffers & (PIPE_CLEAR_DEPTH | PIPE_CLEAR_STENCIL))) {
		enum pipe_format pfmt = pfb->zsbuf->format;
		uint32_t clear = util_pack_z_stencil(pfmt, depth, stencil);
		uint32_t mask = 0;

		if (buffers & PIPE_CLEAR_DEPTH)
			mask |= 0x1;

		if (buffers & PIPE_CLEAR_STENCIL)
			mask |= 0x2;

		OUT_PKT4(ring, REG_A6XX_RB_BLIT_DST_INFO, 1);
		OUT_RING(ring, A6XX_RB_BLIT_DST_INFO_TILE_MODE(TILE6_LINEAR) |
			A6XX_RB_BLIT_DST_INFO_COLOR_FORMAT(fd6_pipe2color(pfmt)));

		OUT_PKT4(ring, REG_A6XX_RB_BLIT_INFO, 1);
		OUT_RING(ring, A6XX_RB_BLIT_INFO_GMEM |
			// XXX UNK0 for separate stencil ??
			A6XX_RB_BLIT_INFO_DEPTH |
			A6XX_RB_BLIT_INFO_CLEAR_MASK(mask));

		OUT_PKT4(ring, REG_A6XX_RB_BLIT_BASE_GMEM, 1);
		OUT_RINGP(ring, MAX_RENDER_TARGETS, &ctx->batch->gmem_patches);

		OUT_PKT4(ring, REG_A6XX_RB_UNKNOWN_88D0, 1);
		OUT_RING(ring, 0);

		OUT_PKT4(ring, REG_A6XX_RB_BLIT_CLEAR_COLOR_DW0, 1);
		OUT_RING(ring, clear);

		fd6_emit_blit(ctx->batch, ring);

		if (pfb->zsbuf && (buffers & PIPE_CLEAR_DEPTH)) {
			struct fd_resource *zsbuf = fd_resource(pfb->zsbuf->texture);
			if (zsbuf->lrz) {
				zsbuf->lrz_valid = true;
				fd6_clear_lrz(ctx->batch, zsbuf, depth);
			}
		}
	}

	return true;
}
Exemplo n.º 6
0
static boolean
lp_setup_try_clear( struct lp_setup_context *setup,
                    const float *color,
                    double depth,
                    unsigned stencil,
                    unsigned flags )
{
   uint32_t zsmask = 0;
   uint32_t zsvalue = 0;
   union lp_rast_cmd_arg color_arg;
   unsigned i;

   LP_DBG(DEBUG_SETUP, "%s state %d\n", __FUNCTION__, setup->state);

   if (flags & PIPE_CLEAR_COLOR) {
      for (i = 0; i < 4; i++)
         color_arg.clear_color[i] = float_to_ubyte(color[i]);
   }

   if (flags & PIPE_CLEAR_DEPTHSTENCIL) {
      unsigned zmask = (flags & PIPE_CLEAR_DEPTH) ? ~0 : 0;
      unsigned smask = (flags & PIPE_CLEAR_STENCIL) ? ~0 : 0;

      zsvalue = util_pack_z_stencil(setup->fb.zsbuf->format,
                                    depth,
                                    stencil);

      zsmask = util_pack_uint_z_stencil(setup->fb.zsbuf->format,
                                        zmask,
                                        smask);
   }

   if (setup->state == SETUP_ACTIVE) {
      struct lp_scene *scene = setup->scene;

      /* Add the clear to existing scene.  In the unusual case where
       * both color and depth-stencil are being cleared when there's
       * already been some rendering, we could discard the currently
       * binned scene and start again, but I don't see that as being
       * a common usage.
       */
      if (flags & PIPE_CLEAR_COLOR) {
         if (!lp_scene_bin_everywhere( scene, 
                                       LP_RAST_OP_CLEAR_COLOR,
                                       color_arg ))
            return FALSE;
      }

      if (flags & PIPE_CLEAR_DEPTHSTENCIL) {
         if (!lp_scene_bin_everywhere( scene,
                                       LP_RAST_OP_CLEAR_ZSTENCIL,
                                       lp_rast_arg_clearzs(zsvalue, zsmask) ))
            return FALSE;
      }
   }
   else {
      /* Put ourselves into the 'pre-clear' state, specifically to try
       * and accumulate multiple clears to color and depth_stencil
       * buffers which the app or state-tracker might issue
       * separately.
       */
      set_scene_state( setup, SETUP_CLEARED, __FUNCTION__ );

      setup->clear.flags |= flags;

      if (flags & PIPE_CLEAR_DEPTHSTENCIL) {
         setup->clear.zsmask |= zsmask;
         setup->clear.zsvalue =
            (setup->clear.zsvalue & ~zsmask) | (zsvalue & zsmask);
      }

      if (flags & PIPE_CLEAR_COLOR) {
         memcpy(setup->clear.color.clear_color,
                &color_arg,
                sizeof color_arg);
      }
   }
   
   return TRUE;
}
Exemplo n.º 7
0
void
i915_clear_emit(struct pipe_context *pipe, unsigned buffers,
                const union pipe_color_union *color,
                double depth, unsigned stencil,
                unsigned destx, unsigned desty, unsigned width, unsigned height)
{
    struct i915_context *i915 = i915_context(pipe);
    uint32_t clear_params, clear_color, clear_depth, clear_stencil,
             clear_color8888, packed_z_stencil;
    union util_color u_color;
    float f_depth = depth;
    struct i915_texture *cbuf_tex, *depth_tex;
    int depth_clear_bbp, color_clear_bbp;

    cbuf_tex = depth_tex = NULL;
    clear_params = 0;
    depth_clear_bbp = color_clear_bbp = 0;

    if (buffers & PIPE_CLEAR_COLOR) {
        struct pipe_surface *cbuf = i915->framebuffer.cbufs[0];

        clear_params |= CLEARPARAM_WRITE_COLOR;
        cbuf_tex = i915_texture(cbuf->texture);

        util_pack_color(color->f, cbuf->format, &u_color);
        if (util_format_get_blocksize(cbuf_tex->b.b.format) == 4) {
            clear_color = u_color.ui;
            color_clear_bbp = 32;
        } else {
            clear_color = (u_color.ui & 0xffff) | (u_color.ui << 16);
            color_clear_bbp = 16;
        }

        /* correctly swizzle clear value */
        if (i915->current.target_fixup_format)
            util_pack_color(color->f, cbuf->format, &u_color);
        else
            util_pack_color(color->f, PIPE_FORMAT_B8G8R8A8_UNORM, &u_color);
        clear_color8888 = u_color.ui;
    } else
        clear_color = clear_color8888 = 0;

    clear_depth = clear_stencil = 0;
    if (buffers & PIPE_CLEAR_DEPTH) {
        struct pipe_surface *zbuf = i915->framebuffer.zsbuf;

        clear_params |= CLEARPARAM_WRITE_DEPTH;
        depth_tex = i915_texture(zbuf->texture);
        packed_z_stencil = util_pack_z_stencil(depth_tex->b.b.format, depth, stencil);

        if (util_format_get_blocksize(depth_tex->b.b.format) == 4) {
            /* Avoid read-modify-write if there's no stencil. */
            if (buffers & PIPE_CLEAR_STENCIL
                    || depth_tex->b.b.format != PIPE_FORMAT_Z24_UNORM_S8_UINT) {
                clear_params |= CLEARPARAM_WRITE_STENCIL;
                clear_stencil = packed_z_stencil >> 24;
            }

            clear_depth = packed_z_stencil & 0xffffff;
            depth_clear_bbp = 32;
        } else {
Exemplo n.º 8
0
void
i915_clear_emit(struct pipe_context *pipe, unsigned buffers, const float *rgba,
                double depth, unsigned stencil,
                unsigned destx, unsigned desty, unsigned width, unsigned height)
{
   struct i915_context *i915 = i915_context(pipe);
   uint32_t clear_params, clear_color, clear_depth, clear_stencil,
            clear_color8888, packed_z_stencil;
   union util_color u_color;
   float f_depth = depth;
   struct i915_texture *cbuf_tex, *depth_tex;

   cbuf_tex = depth_tex = NULL;
   clear_params = 0;

   if (buffers & PIPE_CLEAR_COLOR) {
      struct pipe_surface *cbuf = i915->framebuffer.cbufs[0];

      clear_params |= CLEARPARAM_WRITE_COLOR;
      cbuf_tex = i915_texture(cbuf->texture);
      util_pack_color(rgba, cbuf->format, &u_color);
      if (util_format_get_blocksize(cbuf_tex->b.b.format) == 4)
         clear_color = u_color.ui;
      else
         clear_color = (u_color.ui & 0xffff) | (u_color.ui << 16);

      util_pack_color(rgba, cbuf->format, &u_color);
      clear_color8888 = u_color.ui;
   } else
      clear_color = clear_color8888 = 0;

   clear_depth = clear_stencil = 0;
   if (buffers & PIPE_CLEAR_DEPTH) {
      struct pipe_surface *zbuf = i915->framebuffer.zsbuf;

      clear_params |= CLEARPARAM_WRITE_DEPTH;
      depth_tex = i915_texture(zbuf->texture);
      packed_z_stencil = util_pack_z_stencil(depth_tex->b.b.format, depth, stencil);

      if (util_format_get_blocksize(depth_tex->b.b.format) == 4) {
         /* Avoid read-modify-write if there's no stencil. */
         if (buffers & PIPE_CLEAR_STENCIL
               || depth_tex->b.b.format != PIPE_FORMAT_Z24_UNORM_S8_USCALED) {
            clear_params |= CLEARPARAM_WRITE_STENCIL;
            clear_stencil = packed_z_stencil & 0xff;
            clear_depth = packed_z_stencil;
         } else
            clear_depth = packed_z_stencil & 0xffffff00;
      } else {
         clear_depth = (clear_depth & 0xffff) | (clear_depth << 16);
      }
   }

   if (i915->hardware_dirty)
      i915_emit_hardware_state(i915);

   if (!BEGIN_BATCH(7 + 7)) {
      FLUSH_BATCH(NULL);

      i915_emit_hardware_state(i915);
      i915->vbo_flushed = 1;

      assert(BEGIN_BATCH(7 + 7));
   }

   OUT_BATCH(_3DSTATE_CLEAR_PARAMETERS);
   OUT_BATCH(clear_params | CLEARPARAM_CLEAR_RECT);
   OUT_BATCH(clear_color);
   OUT_BATCH(clear_depth);
   OUT_BATCH(clear_color8888);
   OUT_BATCH_F(f_depth);
   OUT_BATCH(clear_stencil);

   OUT_BATCH(_3DPRIMITIVE | PRIM3D_CLEAR_RECT | 5);
   OUT_BATCH_F(destx + width);
   OUT_BATCH_F(desty + height);
   OUT_BATCH_F(destx);
   OUT_BATCH_F(desty + height);
   OUT_BATCH_F(destx);
   OUT_BATCH_F(desty);

   /* Flush after clear, its expected to be a costly operation.
    * This is not required, just a heuristic
    */
   FLUSH_BATCH(NULL);
}
Exemplo n.º 9
0
/**
 * Fallback for pipe->clear_stencil() function.
 * sw fallback doesn't look terribly useful here.
 * Plus can't use these transfer fallbacks when clearing
 * multisampled surfaces for instance.
 */
void
util_clear_depth_stencil(struct pipe_context *pipe,
                         struct pipe_surface *dst,
                         unsigned clear_flags,
                         double depth,
                         unsigned stencil,
                         unsigned dstx, unsigned dsty,
                         unsigned width, unsigned height)
{
   struct pipe_transfer *dst_trans;
   ubyte *dst_map;
   boolean need_rmw = FALSE;

   if ((clear_flags & PIPE_CLEAR_DEPTHSTENCIL) &&
       ((clear_flags & PIPE_CLEAR_DEPTHSTENCIL) != PIPE_CLEAR_DEPTHSTENCIL) &&
       util_format_is_depth_and_stencil(dst->format))
      need_rmw = TRUE;

   assert(dst->texture);
   if (!dst->texture)
      return;
   dst_trans = pipe_get_transfer(pipe,
                                 dst->texture,
                                 dst->u.tex.level,
                                 dst->u.tex.first_layer,
                                 (need_rmw ? PIPE_TRANSFER_READ_WRITE :
                                     PIPE_TRANSFER_WRITE),
                                 dstx, dsty, width, height);

   dst_map = pipe->transfer_map(pipe, dst_trans);

   assert(dst_map);

   if (dst_map) {
      unsigned dst_stride = dst_trans->stride;
      unsigned zstencil = util_pack_z_stencil(dst->texture->format, depth, stencil);
      unsigned i, j;
      assert(dst_trans->stride > 0);

      switch (util_format_get_blocksize(dst->format)) {
      case 1:
         assert(dst->format == PIPE_FORMAT_S8_UINT);
         if(dst_stride == width)
            memset(dst_map, (ubyte) zstencil, height * width);
         else {
            for (i = 0; i < height; i++) {
               memset(dst_map, (ubyte) zstencil, width);
               dst_map += dst_stride;
            }
         }
         break;
      case 2:
         assert(dst->format == PIPE_FORMAT_Z16_UNORM);
         for (i = 0; i < height; i++) {
            uint16_t *row = (uint16_t *)dst_map;
            for (j = 0; j < width; j++)
               *row++ = (uint16_t) zstencil;
            dst_map += dst_stride;
            }
         break;
      case 4:
         if (!need_rmw) {
            for (i = 0; i < height; i++) {
               uint32_t *row = (uint32_t *)dst_map;
               for (j = 0; j < width; j++)
                  *row++ = zstencil;
               dst_map += dst_stride;
            }
         }
         else {
            uint32_t dst_mask;
            if (dst->format == PIPE_FORMAT_Z24_UNORM_S8_UINT)
               dst_mask = 0xffffff00;
            else {
               assert(dst->format == PIPE_FORMAT_S8_UINT_Z24_UNORM);
               dst_mask = 0xffffff;
            }
            if (clear_flags & PIPE_CLEAR_DEPTH)
               dst_mask = ~dst_mask;
            for (i = 0; i < height; i++) {
               uint32_t *row = (uint32_t *)dst_map;
               for (j = 0; j < width; j++) {
                  uint32_t tmp = *row & dst_mask;
                  *row++ = tmp | (zstencil & ~dst_mask);
               }
               dst_map += dst_stride;
            }
         }
         break;
      case 8:
      {
         uint64_t zstencil = util_pack64_z_stencil(dst->texture->format,
                                                   depth, stencil);

         assert(dst->format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT);

         if (!need_rmw) {
            for (i = 0; i < height; i++) {
               uint64_t *row = (uint64_t *)dst_map;
               for (j = 0; j < width; j++)
                  *row++ = zstencil;
               dst_map += dst_stride;
            }
         }
         else {
            uint64_t src_mask;

            if (clear_flags & PIPE_CLEAR_DEPTH)
               src_mask = 0x00000000ffffffffull;
            else
               src_mask = 0x000000ff00000000ull;

            for (i = 0; i < height; i++) {
               uint64_t *row = (uint64_t *)dst_map;
               for (j = 0; j < width; j++) {
                  uint64_t tmp = *row & ~src_mask;
                  *row++ = tmp | (zstencil & src_mask);
               }
               dst_map += dst_stride;
            }
         }
         break;
      }
      default:
         assert(0);
         break;
      }
   }

   pipe->transfer_unmap(pipe, dst_trans);
   pipe->transfer_destroy(pipe, dst_trans);
}