/** * 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; }
/** * 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; }
/** * 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; }