bool
intel_renderbuffer_resolve_depth(struct intel_context *intel,
				 struct intel_renderbuffer *irb)
{
   if (irb->mt)
      return intel_miptree_slice_resolve_depth(intel,
                                               irb->mt,
                                               irb->mt_level,
                                               irb->mt_layer);

   return false;
}
示例#2
0
/**
 * \param mode  bitmask of GL_MAP_READ_BIT, GL_MAP_WRITE_BIT
 */
static void
intel_tex_map_image_for_swrast(struct intel_context *intel,
			       struct intel_texture_image *intel_image,
			       GLbitfield mode)
{
   int level;
   int face;
   struct intel_mipmap_tree *mt;
   unsigned int x, y;

   if (!intel_image || !intel_image->mt)
      return;

   level = intel_image->base.Base.Level;
   face = intel_image->base.Base.Face;
   mt = intel_image->mt;

   for (int i = 0; i < mt->level[level].depth; i++)
      intel_miptree_slice_resolve_depth(intel, mt, level, i);

   if (mt->target == GL_TEXTURE_3D ||
       mt->target == GL_TEXTURE_2D_ARRAY ||
       mt->target == GL_TEXTURE_1D_ARRAY) {
      int i;

      /* ImageOffsets[] is only used for swrast's fetch_texel_3d, so we can't
       * share code with the normal path.
       */
      for (i = 0; i < mt->level[level].depth; i++) {
	 intel_miptree_get_image_offset(mt, level, i, &x, &y);
	 intel_image->base.ImageOffsets[i] = x + y * (mt->region->pitch /
                                                      mt->region->cpp);
      }

      DBG("%s \n", __FUNCTION__);

      intel_image->base.Map = intel_miptree_map_raw(intel, mt);
   } else {
      assert(intel_image->base.Base.Depth == 1);
      intel_miptree_get_image_offset(mt, level, face, &x, &y);

      DBG("%s: (%d,%d) -> (%d, %d)/%d\n",
	  __FUNCTION__, face, level, x, y, mt->region->pitch);

      intel_image->base.Map = intel_miptree_map_raw(intel, mt) +
	 x * mt->cpp + y * mt->region->pitch;
   }

   assert(mt->region->pitch % mt->region->cpp == 0);
   intel_image->base.RowStride = mt->region->pitch / mt->region->cpp;
}
示例#3
0
/**
 * Implements a rectangular block transfer (blit) of pixels between two
 * miptrees.
 *
 * Our blitter can operate on 1, 2, or 4-byte-per-pixel data, with generous,
 * but limited, pitches and sizes allowed.
 *
 * The src/dst coordinates are relative to the given level/slice of the
 * miptree.
 *
 * If @src_flip or @dst_flip is set, then the rectangle within that miptree
 * will be inverted (including scanline order) when copying.  This is common
 * in GL when copying between window system and user-created
 * renderbuffers/textures.
 */
bool
intel_miptree_blit(struct brw_context *brw,
                   struct intel_mipmap_tree *src_mt,
                   int src_level, int src_slice,
                   uint32_t src_x, uint32_t src_y, bool src_flip,
                   struct intel_mipmap_tree *dst_mt,
                   int dst_level, int dst_slice,
                   uint32_t dst_x, uint32_t dst_y, bool dst_flip,
                   uint32_t width, uint32_t height,
                   GLenum logicop)
{
   /* No sRGB decode or encode is done by the hardware blitter, which is
    * consistent with what we want in the callers (glCopyTexSubImage(),
    * glBlitFramebuffer(), texture validation, etc.).
    */
   gl_format src_format = _mesa_get_srgb_format_linear(src_mt->format);
   gl_format dst_format = _mesa_get_srgb_format_linear(dst_mt->format);

   /* The blitter doesn't support doing any format conversions.  We do also
    * support blitting ARGB8888 to XRGB8888 (trivial, the values dropped into
    * the X channel don't matter), and XRGB8888 to ARGB8888 by setting the A
    * channel to 1.0 at the end.
    */
   if (src_format != dst_format &&
      ((src_format != MESA_FORMAT_ARGB8888 &&
        src_format != MESA_FORMAT_XRGB8888) ||
       (dst_format != MESA_FORMAT_ARGB8888 &&
        dst_format != MESA_FORMAT_XRGB8888))) {
      perf_debug("%s: Can't use hardware blitter from %s to %s, "
                 "falling back.\n", __FUNCTION__,
                 _mesa_get_format_name(src_format),
                 _mesa_get_format_name(dst_format));
      return false;
   }

   /* According to the Ivy Bridge PRM, Vol1 Part4, section 1.2.1.2 (Graphics
    * Data Size Limitations):
    *
    *    The BLT engine is capable of transferring very large quantities of
    *    graphics data. Any graphics data read from and written to the
    *    destination is permitted to represent a number of pixels that
    *    occupies up to 65,536 scan lines and up to 32,768 bytes per scan line
    *    at the destination. The maximum number of pixels that may be
    *    represented per scan line’s worth of graphics data depends on the
    *    color depth.
    *
    * Furthermore, intelEmitCopyBlit (which is called below) uses a signed
    * 16-bit integer to represent buffer pitch, so it can only handle buffer
    * pitches < 32k.
    *
    * As a result of these two limitations, we can only use the blitter to do
    * this copy when the region's pitch is less than 32k.
    */
   if (src_mt->region->pitch > 32768 ||
       dst_mt->region->pitch > 32768) {
      perf_debug("Falling back due to >32k pitch\n");
      return false;
   }

   /* The blitter has no idea about HiZ or fast color clears, so we need to
    * resolve the miptrees before we do anything.
    */
   intel_miptree_slice_resolve_depth(brw, src_mt, src_level, src_slice);
   intel_miptree_slice_resolve_depth(brw, dst_mt, dst_level, dst_slice);
   intel_miptree_resolve_color(brw, src_mt);
   intel_miptree_resolve_color(brw, dst_mt);

   if (src_flip)
      src_y = src_mt->level[src_level].height - src_y - height;

   if (dst_flip)
      dst_y = dst_mt->level[dst_level].height - dst_y - height;

   int src_pitch = src_mt->region->pitch;
   if (src_flip != dst_flip)
      src_pitch = -src_pitch;

   uint32_t src_image_x, src_image_y;
   intel_miptree_get_image_offset(src_mt, src_level, src_slice,
                                  &src_image_x, &src_image_y);
   src_x += src_image_x;
   src_y += src_image_y;

   uint32_t dst_image_x, dst_image_y;
   intel_miptree_get_image_offset(dst_mt, dst_level, dst_slice,
                                  &dst_image_x, &dst_image_y);
   dst_x += dst_image_x;
   dst_y += dst_image_y;

   if (!intelEmitCopyBlit(brw,
                          src_mt->cpp,
                          src_pitch,
                          src_mt->region->bo, src_mt->offset,
                          src_mt->region->tiling,
                          dst_mt->region->pitch,
                          dst_mt->region->bo, dst_mt->offset,
                          dst_mt->region->tiling,
                          src_x, src_y,
                          dst_x, dst_y,
                          width, height,
                          logicop)) {
      return false;
   }

   if (src_mt->format == MESA_FORMAT_XRGB8888 &&
       dst_mt->format == MESA_FORMAT_ARGB8888) {
      intel_miptree_set_alpha_to_one(brw, dst_mt,
                                     dst_x, dst_y,
                                     width, height);
   }

   return true;
}
示例#4
0
文件: brw_blorp.c 项目: Echelon9/mesa
static void
blorp_surf_for_miptree(struct brw_context *brw,
                       struct blorp_surf *surf,
                       struct intel_mipmap_tree *mt,
                       bool is_render_target,
                       uint32_t safe_aux_usage,
                       unsigned *level,
                       unsigned start_layer, unsigned num_layers,
                       struct isl_surf tmp_surfs[2])
{
   if (mt->msaa_layout == INTEL_MSAA_LAYOUT_UMS ||
       mt->msaa_layout == INTEL_MSAA_LAYOUT_CMS) {
      const unsigned num_samples = MAX2(1, mt->num_samples);
      for (unsigned i = 0; i < num_layers; i++) {
         for (unsigned s = 0; s < num_samples; s++) {
            const unsigned phys_layer = (start_layer + i) * num_samples + s;
            intel_miptree_check_level_layer(mt, *level, phys_layer);
         }
      }
   } else {
      for (unsigned i = 0; i < num_layers; i++)
         intel_miptree_check_level_layer(mt, *level, start_layer + i);
   }

   intel_miptree_get_isl_surf(brw, mt, &tmp_surfs[0]);
   surf->surf = &tmp_surfs[0];
   surf->addr = (struct blorp_address) {
      .buffer = mt->bo,
      .offset = mt->offset,
      .read_domains = is_render_target ? I915_GEM_DOMAIN_RENDER :
                                         I915_GEM_DOMAIN_SAMPLER,
      .write_domain = is_render_target ? I915_GEM_DOMAIN_RENDER : 0,
   };

   if (brw->gen == 6 && mt->format == MESA_FORMAT_S_UINT8 &&
       mt->array_layout == ALL_SLICES_AT_EACH_LOD) {
      /* Sandy bridge stencil and HiZ use this ALL_SLICES_AT_EACH_LOD hack in
       * order to allow for layered rendering.  The hack makes each LOD of the
       * stencil or HiZ buffer a single tightly packed array surface at some
       * offset into the surface.  Since ISL doesn't know how to deal with the
       * crazy ALL_SLICES_AT_EACH_LOD layout and since we have to do a manual
       * offset of it anyway, we might as well do the offset here and keep the
       * hacks inside the i965 driver.
       *
       * See also gen6_depth_stencil_state.c
       */
      uint32_t offset;
      apply_gen6_stencil_hiz_offset(&tmp_surfs[0], mt, *level, &offset);
      surf->addr.offset += offset;
      *level = 0;
   }

   struct isl_surf *aux_surf = &tmp_surfs[1];
   intel_miptree_get_aux_isl_surf(brw, mt, aux_surf, &surf->aux_usage);

   if (surf->aux_usage != ISL_AUX_USAGE_NONE) {
      if (surf->aux_usage == ISL_AUX_USAGE_HIZ) {
         /* If we're not going to use it as a depth buffer, resolve HiZ */
         if (!(safe_aux_usage & (1 << ISL_AUX_USAGE_HIZ))) {
            for (unsigned i = 0; i < num_layers; i++) {
               intel_miptree_slice_resolve_depth(brw, mt, *level,
                                                 start_layer + i);

               /* If we're rendering to it then we'll need a HiZ resolve once
                * we're done before we can use it with HiZ again.
                */
               if (is_render_target)
                  intel_miptree_slice_set_needs_hiz_resolve(mt, *level,
                                                            start_layer + i);
            }
            surf->aux_usage = ISL_AUX_USAGE_NONE;
         }
      } else if (!(safe_aux_usage & (1 << surf->aux_usage))) {
         uint32_t flags = 0;
         if (safe_aux_usage & (1 << ISL_AUX_USAGE_CCS_E))
            flags |= INTEL_MIPTREE_IGNORE_CCS_E;

         intel_miptree_resolve_color(brw, mt,
                                     *level, start_layer, num_layers, flags);

         assert(!intel_miptree_has_color_unresolved(mt, *level, 1,
                                                    start_layer, num_layers));
         surf->aux_usage = ISL_AUX_USAGE_NONE;
      }
   }

   if (is_render_target)
      intel_miptree_used_for_rendering(brw, mt, *level,
                                       start_layer, num_layers);

   if (surf->aux_usage != ISL_AUX_USAGE_NONE) {
      /* We only really need a clear color if we also have an auxiliary
       * surface.  Without one, it does nothing.
       */
      surf->clear_color = intel_miptree_get_isl_clear_color(brw, mt);

      surf->aux_surf = aux_surf;
      surf->aux_addr = (struct blorp_address) {
         .read_domains = is_render_target ? I915_GEM_DOMAIN_RENDER :
                                            I915_GEM_DOMAIN_SAMPLER,
         .write_domain = is_render_target ? I915_GEM_DOMAIN_RENDER : 0,
      };

      if (mt->mcs_buf) {
         surf->aux_addr.buffer = mt->mcs_buf->bo;
         surf->aux_addr.offset = mt->mcs_buf->offset;
      } else {
         assert(surf->aux_usage == ISL_AUX_USAGE_HIZ);
         struct intel_mipmap_tree *hiz_mt = mt->hiz_buf->mt;
         if (hiz_mt) {
            surf->aux_addr.buffer = hiz_mt->bo;
            if (brw->gen == 6 &&
                hiz_mt->array_layout == ALL_SLICES_AT_EACH_LOD) {
               /* gen6 requires the HiZ buffer to be manually offset to the
                * right location.  We could fixup the surf but it doesn't
                * matter since most of those fields don't matter.
                */
               apply_gen6_stencil_hiz_offset(aux_surf, hiz_mt, *level,
                                             &surf->aux_addr.offset);
            } else {
               surf->aux_addr.offset = 0;
            }
            assert(hiz_mt->pitch == aux_surf->row_pitch);
         } else {
            surf->aux_addr.buffer = mt->hiz_buf->aux_base.bo;
            surf->aux_addr.offset = mt->hiz_buf->aux_base.offset;
         }
      }
   } else {
      surf->aux_addr = (struct blorp_address) {
         .buffer = NULL,
      };
      memset(&surf->clear_color, 0, sizeof(surf->clear_color));
   }
   assert((surf->aux_usage == ISL_AUX_USAGE_NONE) ==
          (surf->aux_addr.buffer == NULL));
}