Ejemplo n.º 1
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)
{
   /* The blitter doesn't understand multisampling at all. */
   if (src_mt->num_samples > 0 || dst_mt->num_samples > 0)
      return false;

   /* 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.).
    */
   mesa_format src_format = _mesa_get_srgb_format_linear(src_mt->format);
   mesa_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_B8G8R8A8_UNORM &&
        src_format != MESA_FORMAT_B8G8R8X8_UNORM) ||
       (dst_format != MESA_FORMAT_B8G8R8A8_UNORM &&
        dst_format != MESA_FORMAT_B8G8R8X8_UNORM))) {
      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 miptree's pitch is less than 32k.
    */
   if (src_mt->pitch >= 32768 ||
       dst_mt->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 = minify(src_mt->physical_height0, src_level - src_mt->first_level) - src_y - height;

   if (dst_flip)
      dst_y = minify(dst_mt->physical_height0, dst_level - dst_mt->first_level) - dst_y - height;

   int src_pitch = src_mt->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;

   /* The blitter interprets the 16-bit src x/y as a signed 16-bit value,
    * where negative values are invalid.  The values we're working with are
    * unsigned, so make sure we don't overflow.
    */
   if (src_x >= 32768 || src_y >= 32768) {
      perf_debug("Falling back due to >=32k src offset (%d, %d)\n",
                 src_x, src_y);
      return false;
   }

   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;

   /* The blitter interprets the 16-bit destination x/y as a signed 16-bit
    * value.  The values we're working with are unsigned, so make sure we
    * don't overflow.
    */
   if (dst_x >= 32768 || dst_y >= 32768) {
      perf_debug("Falling back due to >=32k dst offset (%d, %d)\n",
                 dst_x, dst_y);
      return false;
   }

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

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

   return true;
}
Ejemplo n.º 2
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 intel_context *intel,
                   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;
   }

   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(intel,
                          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(intel, dst_mt,
                                     dst_x, dst_y,
                                     width, height);
   }

   return true;
}
Ejemplo n.º 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,
                   enum gl_logicop_mode logicop)
{
   /* The blitter doesn't understand multisampling at all. */
   if (src_mt->surf.samples > 1 || dst_mt->surf.samples > 1)
      return false;

   /* No sRGB decode or encode is done by the hardware blitter, which is
    * consistent with what we want in many callers (glCopyTexSubImage(),
    * texture validation, etc.).
    */
   mesa_format src_format = _mesa_get_srgb_format_linear(src_mt->format);
   mesa_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. Also trivially ARGB2101010 to XRGB2101010,
    * but not XRGB2101010 to ARGB2101010 yet.
    */
   if (!intel_miptree_blit_compatible_formats(src_format, dst_format)) {
      perf_debug("%s: Can't use hardware blitter from %s to %s, "
                 "falling back.\n", __func__,
                 _mesa_get_format_name(src_format),
                 _mesa_get_format_name(dst_format));
      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_access_raw(brw, src_mt, src_level, src_slice, false);
   intel_miptree_access_raw(brw, dst_mt, dst_level, dst_slice, true);

   if (src_flip) {
      const unsigned h0 = src_mt->surf.phys_level0_sa.height;
      src_y = minify(h0, src_level - src_mt->first_level) - src_y - height;
   }

   if (dst_flip) {
      const unsigned h0 = dst_mt->surf.phys_level0_sa.height;
      dst_y = minify(h0, dst_level - dst_mt->first_level) - dst_y - height;
   }

   uint32_t src_image_x, src_image_y, dst_image_x, dst_image_y;
   intel_miptree_get_image_offset(src_mt, src_level, src_slice,
                                  &src_image_x, &src_image_y);
   intel_miptree_get_image_offset(dst_mt, dst_level, dst_slice,
                                  &dst_image_x, &dst_image_y);
   src_x += src_image_x;
   src_y += src_image_y;
   dst_x += dst_image_x;
   dst_y += dst_image_y;

   if (!emit_miptree_blit(brw, src_mt, src_x, src_y,
                          dst_mt, dst_x, dst_y, width, height,
                          src_flip != dst_flip, logicop)) {
      return false;
   }

   /* XXX This could be done in a single pass using XY_FULL_MONO_PATTERN_BLT */
   if (_mesa_get_format_bits(src_format, GL_ALPHA_BITS) == 0 &&
       _mesa_get_format_bits(dst_format, GL_ALPHA_BITS) > 0) {
      intel_miptree_set_alpha_to_one(brw, dst_mt,
                                     dst_x, dst_y,
                                     width, height);
   }

   return true;
}