Esempio n. 1
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;
}
Esempio n. 2
0
/*
 * Try to clear one color buffer of the attached fb, either by binning a clear
 * command or queuing up the clear for later (when binning is started).
 */
static boolean
lp_setup_try_clear_color_buffer(struct lp_setup_context *setup,
                                const union pipe_color_union *color,
                                unsigned cbuf)
{
   union lp_rast_cmd_arg clearrb_arg;
   union util_color uc;
   enum pipe_format format = setup->fb.cbufs[cbuf]->format;

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

   if (util_format_is_pure_integer(format)) {
      /*
       * We expect int/uint clear values here, though some APIs
       * might disagree (but in any case util_pack_color()
       * couldn't handle it)...
       */
      if (util_format_is_pure_sint(format)) {
         util_format_write_4i(format, color->i, 0, &uc, 0, 0, 0, 1, 1);
      }
      else {
         assert(util_format_is_pure_uint(format));
         util_format_write_4ui(format, color->ui, 0, &uc, 0, 0, 0, 1, 1);
      }
   }
   else {
      util_pack_color(color->f, format, &uc);
   }

   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.
       */
      struct lp_rast_clear_rb *cc_scene =
         (struct lp_rast_clear_rb *)
            lp_scene_alloc_aligned(scene, sizeof(struct lp_rast_clear_rb), 8);

      if (!cc_scene) {
         return FALSE;
      }

      cc_scene->cbuf = cbuf;
      cc_scene->color_val = uc;
      clearrb_arg.clear_rb = cc_scene;

      if (!lp_scene_bin_everywhere(scene,
                                   LP_RAST_OP_CLEAR_COLOR,
                                   clearrb_arg))
         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__ );

      assert(PIPE_CLEAR_COLOR0 == (1 << 2));
      setup->clear.flags |= 1 << (cbuf + 2);
      setup->clear.color_val[cbuf] = uc;
   }

   return TRUE;
}
Esempio n. 3
0
/**
 * Fallback for pipe->clear_render_target() function.
 * XXX this looks too hackish to be really useful.
 * cpp > 4 looks like a gross hack at best...
 * Plus can't use these transfer fallbacks when clearing
 * multisampled surfaces for instance.
 * Clears all bound layers.
 */
void
util_clear_render_target(struct pipe_context *pipe,
                         struct pipe_surface *dst,
                         const union pipe_color_union *color,
                         unsigned dstx, unsigned dsty,
                         unsigned width, unsigned height)
{
   struct pipe_transfer *dst_trans;
   ubyte *dst_map;
   union util_color uc;
   unsigned max_layer;

   assert(dst->texture);
   if (!dst->texture)
      return;

   if (dst->texture->target == PIPE_BUFFER) {
      /*
       * The fill naturally works on the surface format, however
       * the transfer uses resource format which is just bytes for buffers.
       */
      unsigned dx, w;
      unsigned pixstride = util_format_get_blocksize(dst->format);
      dx = (dst->u.buf.first_element + dstx) * pixstride;
      w = width * pixstride;
      max_layer = 0;
      dst_map = pipe_transfer_map(pipe,
                                  dst->texture,
                                  0, 0,
                                  PIPE_TRANSFER_WRITE,
                                  dx, 0, w, 1,
                                  &dst_trans);
   }
   else {
      max_layer = dst->u.tex.last_layer - dst->u.tex.first_layer;
      dst_map = pipe_transfer_map_3d(pipe,
                                     dst->texture,
                                     dst->u.tex.level,
                                     PIPE_TRANSFER_WRITE,
                                     dstx, dsty, dst->u.tex.first_layer,
                                     width, height, max_layer + 1, &dst_trans);
   }

   assert(dst_map);

   if (dst_map) {
      enum pipe_format format = dst->format;
      assert(dst_trans->stride > 0);

      if (util_format_is_pure_integer(format)) {
         /*
          * We expect int/uint clear values here, though some APIs
          * might disagree (but in any case util_pack_color()
          * couldn't handle it)...
          */
         if (util_format_is_pure_sint(format)) {
            util_format_write_4i(format, color->i, 0, &uc, 0, 0, 0, 1, 1);
         }
         else {
            assert(util_format_is_pure_uint(format));
            util_format_write_4ui(format, color->ui, 0, &uc, 0, 0, 0, 1, 1);
         }
      }
      else {
         util_pack_color(color->f, format, &uc);
      }

      util_fill_box(dst_map, dst->format,
                    dst_trans->stride, dst_trans->layer_stride,
                    0, 0, 0, width, height, max_layer + 1, &uc);

      pipe->transfer_unmap(pipe, dst_trans);
   }
}
Esempio n. 4
0
/**
 * Clear the rasterizer's current color tile.
 * This is a bin command called during bin processing.
 */
static void
lp_rast_clear_color(struct lp_rasterizer_task *task,
                    const union lp_rast_cmd_arg arg)
{
   const struct lp_scene *scene = task->scene;

   if (scene->fb.nr_cbufs) {
      unsigned i;
      union util_color uc;

      if (util_format_is_pure_integer(scene->fb.cbufs[0]->format)) {
         /*
          * We expect int/uint clear values here, though some APIs
          * might disagree (but in any case util_pack_color()
          * couldn't handle it)...
          */
         LP_DBG(DEBUG_RAST, "%s pure int 0x%x,0x%x,0x%x,0x%x\n", __FUNCTION__,
                    arg.clear_color.ui[0],
                    arg.clear_color.ui[1],
                    arg.clear_color.ui[2],
                    arg.clear_color.ui[3]);

         for (i = 0; i < scene->fb.nr_cbufs; i++) {
            enum pipe_format format = scene->fb.cbufs[i]->format;

            if (util_format_is_pure_sint(format)) {
               util_format_write_4i(format, arg.clear_color.i, 0, &uc, 0, 0, 0, 1, 1);
            }
            else {
               assert(util_format_is_pure_uint(format));
               util_format_write_4ui(format, arg.clear_color.ui, 0, &uc, 0, 0, 0, 1, 1);
            }

            util_fill_rect(scene->cbufs[i].map,
                           scene->fb.cbufs[i]->format,
                           scene->cbufs[i].stride,
                           task->x,
                           task->y,
                           TILE_SIZE,
                           TILE_SIZE,
                           &uc);
         }
      }
      else {
         uint8_t clear_color[4];

         for (i = 0; i < 4; ++i) {
            clear_color[i] = float_to_ubyte(arg.clear_color.f[i]);
         }

         LP_DBG(DEBUG_RAST, "%s 0x%x,0x%x,0x%x,0x%x\n", __FUNCTION__,
                    clear_color[0],
                    clear_color[1],
                    clear_color[2],
                    clear_color[3]);

         for (i = 0; i < scene->fb.nr_cbufs; i++) {

            util_pack_color(arg.clear_color.f,
                            scene->fb.cbufs[i]->format, &uc);

            util_fill_rect(scene->cbufs[i].map,
                           scene->fb.cbufs[i]->format,
                           scene->cbufs[i].stride,
                           task->x,
                           task->y,
                           TILE_SIZE,
                           TILE_SIZE,
                           &uc);
         }
      }
   }

   LP_COUNT(nr_color_tile_clear);
}