17ec681f3Smrg/*
27ec681f3Smrg * Copyright © 2018 Intel Corporation
37ec681f3Smrg *
47ec681f3Smrg * Permission is hereby granted, free of charge, to any person obtaining a
57ec681f3Smrg * copy of this software and associated documentation files (the "Software"),
67ec681f3Smrg * to deal in the Software without restriction, including without limitation
77ec681f3Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
87ec681f3Smrg * and/or sell copies of the Software, and to permit persons to whom the
97ec681f3Smrg * Software is furnished to do so, subject to the following conditions:
107ec681f3Smrg *
117ec681f3Smrg * The above copyright notice and this permission notice shall be included
127ec681f3Smrg * in all copies or substantial portions of the Software.
137ec681f3Smrg *
147ec681f3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
157ec681f3Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
167ec681f3Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
177ec681f3Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
187ec681f3Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
197ec681f3Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
207ec681f3Smrg * DEALINGS IN THE SOFTWARE.
217ec681f3Smrg */
227ec681f3Smrg
237ec681f3Smrg/* blt command encoding for gen4/5 */
247ec681f3Smrg#include "crocus_context.h"
257ec681f3Smrg
267ec681f3Smrg#include "crocus_genx_macros.h"
277ec681f3Smrg#include "crocus_genx_protos.h"
287ec681f3Smrg#include "crocus_resource.h"
297ec681f3Smrg
307ec681f3Smrg#define FILE_DEBUG_FLAG DEBUG_BLIT
317ec681f3Smrg
327ec681f3Smrg#if GFX_VER <= 5
337ec681f3Smrg
347ec681f3Smrgstatic uint32_t
357ec681f3Smrgcolor_depth_for_cpp(int cpp)
367ec681f3Smrg{
377ec681f3Smrg   switch (cpp) {
387ec681f3Smrg   case 4: return COLOR_DEPTH__32bit;
397ec681f3Smrg   case 2: return COLOR_DEPTH__565;
407ec681f3Smrg   case 1: return COLOR_DEPTH__8bit;
417ec681f3Smrg   default:
427ec681f3Smrg      unreachable("not reached");
437ec681f3Smrg   }
447ec681f3Smrg}
457ec681f3Smrg
467ec681f3Smrgstatic void
477ec681f3Smrgblt_set_alpha_to_one(struct crocus_batch *batch,
487ec681f3Smrg		     struct crocus_resource *dst,
497ec681f3Smrg		     int x, int y, int width, int height)
507ec681f3Smrg{
517ec681f3Smrg   const struct isl_format_layout *fmtl = isl_format_get_layout(dst->surf.format);
527ec681f3Smrg   unsigned cpp = fmtl->bpb / 8;
537ec681f3Smrg   uint32_t pitch = dst->surf.row_pitch_B;
547ec681f3Smrg
557ec681f3Smrg   if (dst->surf.tiling != ISL_TILING_LINEAR)
567ec681f3Smrg      pitch /= 4;
577ec681f3Smrg   /* We need to split the blit into chunks that each fit within the blitter's
587ec681f3Smrg    * restrictions.  We can't use a chunk size of 32768 because we need to
597ec681f3Smrg    * ensure that src_tile_x + chunk_size fits.  We choose 16384 because it's
607ec681f3Smrg    * a nice round power of two, big enough that performance won't suffer, and
617ec681f3Smrg    * small enough to guarantee everything fits.
627ec681f3Smrg    */
637ec681f3Smrg   const uint32_t max_chunk_size = 16384;
647ec681f3Smrg
657ec681f3Smrg   for (uint32_t chunk_x = 0; chunk_x < width; chunk_x += max_chunk_size) {
667ec681f3Smrg      for (uint32_t chunk_y = 0; chunk_y < height; chunk_y += max_chunk_size) {
677ec681f3Smrg         const uint32_t chunk_w = MIN2(max_chunk_size, width - chunk_x);
687ec681f3Smrg         const uint32_t chunk_h = MIN2(max_chunk_size, height - chunk_y);
697ec681f3Smrg         uint32_t tile_x, tile_y;
707ec681f3Smrg         uint64_t offset_B;
717ec681f3Smrg         ASSERTED uint32_t z_offset_el, array_offset;
727ec681f3Smrg         isl_tiling_get_intratile_offset_el(dst->surf.tiling, dst->surf.dim,
737ec681f3Smrg                                            dst->surf.msaa_layout,
747ec681f3Smrg                                            cpp * 8, dst->surf.samples,
757ec681f3Smrg                                            dst->surf.row_pitch_B,
767ec681f3Smrg                                            dst->surf.array_pitch_el_rows,
777ec681f3Smrg                                            chunk_x, chunk_y, 0, 0,
787ec681f3Smrg                                            &offset_B,
797ec681f3Smrg                                            &tile_x, &tile_y,
807ec681f3Smrg                                            &z_offset_el, &array_offset);
817ec681f3Smrg         assert(z_offset_el == 0);
827ec681f3Smrg         assert(array_offset == 0);
837ec681f3Smrg	 crocus_emit_cmd(batch, GENX(XY_COLOR_BLT), xyblt) {
847ec681f3Smrg            xyblt.TilingEnable = dst->surf.tiling != ISL_TILING_LINEAR;
857ec681f3Smrg            xyblt.ColorDepth = color_depth_for_cpp(cpp);
867ec681f3Smrg            xyblt.RasterOperation = 0xF0;
877ec681f3Smrg            xyblt.DestinationPitch = pitch;
887ec681f3Smrg            xyblt._32bppByteMask = 2;
897ec681f3Smrg            xyblt.DestinationBaseAddress = rw_bo(dst->bo, offset_B);
907ec681f3Smrg            xyblt.DestinationX1Coordinate = tile_x;
917ec681f3Smrg            xyblt.DestinationY1Coordinate = tile_y;
927ec681f3Smrg            xyblt.DestinationX2Coordinate = tile_x + chunk_w;
937ec681f3Smrg            xyblt.DestinationY2Coordinate = tile_y + chunk_h;
947ec681f3Smrg            xyblt.SolidPatternColor = 0xffffffff;
957ec681f3Smrg	 }
967ec681f3Smrg      }
977ec681f3Smrg   }
987ec681f3Smrg}
997ec681f3Smrg
1007ec681f3Smrgstatic bool validate_blit_for_blt(struct crocus_batch *batch,
1017ec681f3Smrg                                  const struct pipe_blit_info *info)
1027ec681f3Smrg{
1037ec681f3Smrg   /* If the source and destination are the same size with no mirroring,
1047ec681f3Smrg    * the rectangles are within the size of the texture and there is no
1057ec681f3Smrg    * scissor, then we can probably use the blit engine.
1067ec681f3Smrg    */
1077ec681f3Smrg   if (info->dst.box.width != info->src.box.width ||
1087ec681f3Smrg       info->dst.box.height != info->src.box.height)
1097ec681f3Smrg      return false;
1107ec681f3Smrg
1117ec681f3Smrg   if (info->scissor_enable)
1127ec681f3Smrg      return false;
1137ec681f3Smrg
1147ec681f3Smrg   if (info->dst.box.height < 0 || info->src.box.height < 0)
1157ec681f3Smrg      return false;
1167ec681f3Smrg
1177ec681f3Smrg   if (info->dst.box.depth > 1 || info->src.box.depth > 1)
1187ec681f3Smrg      return false;
1197ec681f3Smrg
1207ec681f3Smrg   const struct util_format_description *desc =
1217ec681f3Smrg      util_format_description(info->src.format);
1227ec681f3Smrg   int i = util_format_get_first_non_void_channel(info->src.format);
1237ec681f3Smrg   if (i == -1)
1247ec681f3Smrg      return false;
1257ec681f3Smrg
1267ec681f3Smrg   /* can't do the alpha to 1 setting for these. */
1277ec681f3Smrg   if ((util_format_has_alpha1(info->src.format) &&
1287ec681f3Smrg        util_format_has_alpha(info->dst.format) &&
1297ec681f3Smrg        desc->channel[i].size > 8))
1307ec681f3Smrg      return false;
1317ec681f3Smrg   return true;
1327ec681f3Smrg}
1337ec681f3Smrg
1347ec681f3Smrgstatic inline int crocus_resource_blt_pitch(struct crocus_resource *res)
1357ec681f3Smrg{
1367ec681f3Smrg   int pitch = res->surf.row_pitch_B;
1377ec681f3Smrg   if (res->surf.tiling != ISL_TILING_LINEAR)
1387ec681f3Smrg      pitch /= 4;
1397ec681f3Smrg   return pitch;
1407ec681f3Smrg}
1417ec681f3Smrg
1427ec681f3Smrg
1437ec681f3Smrgstatic bool emit_copy_blt(struct crocus_batch *batch,
1447ec681f3Smrg                          struct crocus_resource *src,
1457ec681f3Smrg                          struct crocus_resource *dst,
1467ec681f3Smrg                          unsigned cpp,
1477ec681f3Smrg                          int32_t src_pitch,
1487ec681f3Smrg                          unsigned src_offset,
1497ec681f3Smrg                          int32_t dst_pitch,
1507ec681f3Smrg                          unsigned dst_offset,
1517ec681f3Smrg                          uint16_t src_x, uint16_t src_y,
1527ec681f3Smrg                          uint16_t dst_x, uint16_t dst_y,
1537ec681f3Smrg                          uint16_t w, uint16_t h)
1547ec681f3Smrg
1557ec681f3Smrg{
1567ec681f3Smrg   uint32_t src_tile_w, src_tile_h;
1577ec681f3Smrg   uint32_t dst_tile_w, dst_tile_h;
1587ec681f3Smrg   int dst_y2 = dst_y + h;
1597ec681f3Smrg   int dst_x2 = dst_x + w;
1607ec681f3Smrg
1617ec681f3Smrg   DBG("%s src:buf(%p)/%d+%d %d,%d dst:buf(%p)/%d+%d %d,%d sz:%dx%d\n",
1627ec681f3Smrg       __func__,
1637ec681f3Smrg       src, src_pitch, src_offset, src_x, src_y,
1647ec681f3Smrg       dst, dst_pitch, dst_offset, dst_x, dst_y, w, h);
1657ec681f3Smrg
1667ec681f3Smrg   isl_get_tile_dims(src->surf.tiling, cpp, &src_tile_w, &src_tile_h);
1677ec681f3Smrg   isl_get_tile_dims(dst->surf.tiling, cpp, &dst_tile_w, &dst_tile_h);
1687ec681f3Smrg
1697ec681f3Smrg   /* For Tiled surfaces, the pitch has to be a multiple of the Tile width
1707ec681f3Smrg    * (X direction width of the Tile). This is ensured while allocating the
1717ec681f3Smrg    * buffer object.
1727ec681f3Smrg    */
1737ec681f3Smrg   assert(src->surf.tiling == ISL_TILING_LINEAR || (src_pitch % src_tile_w) == 0);
1747ec681f3Smrg   assert(dst->surf.tiling == ISL_TILING_LINEAR || (dst_pitch % dst_tile_w) == 0);
1757ec681f3Smrg
1767ec681f3Smrg   /* For big formats (such as floating point), do the copy using 16 or
1777ec681f3Smrg    * 32bpp and multiply the coordinates.
1787ec681f3Smrg    */
1797ec681f3Smrg   if (cpp > 4) {
1807ec681f3Smrg      if (cpp % 4 == 2) {
1817ec681f3Smrg         dst_x *= cpp / 2;
1827ec681f3Smrg         dst_x2 *= cpp / 2;
1837ec681f3Smrg         src_x *= cpp / 2;
1847ec681f3Smrg         cpp = 2;
1857ec681f3Smrg      } else {
1867ec681f3Smrg         assert(cpp % 4 == 0);
1877ec681f3Smrg         dst_x *= cpp / 4;
1887ec681f3Smrg         dst_x2 *= cpp / 4;
1897ec681f3Smrg         src_x *= cpp / 4;
1907ec681f3Smrg         cpp = 4;
1917ec681f3Smrg      }
1927ec681f3Smrg   }
1937ec681f3Smrg
1947ec681f3Smrg   /* Blit pitch must be dword-aligned.  Otherwise, the hardware appears to drop
1957ec681f3Smrg    * the low bits.  Offsets must be naturally aligned.
1967ec681f3Smrg    */
1977ec681f3Smrg   if (src_pitch % 4 != 0 || src_offset % cpp != 0 ||
1987ec681f3Smrg       dst_pitch % 4 != 0 || dst_offset % cpp != 0)
1997ec681f3Smrg     return false;
2007ec681f3Smrg
2017ec681f3Smrg   /* For tiled source and destination, pitch value should be specified
2027ec681f3Smrg    * as a number of Dwords.
2037ec681f3Smrg    */
2047ec681f3Smrg   if (dst->surf.tiling != ISL_TILING_LINEAR)
2057ec681f3Smrg      dst_pitch /= 4;
2067ec681f3Smrg
2077ec681f3Smrg   if (src->surf.tiling != ISL_TILING_LINEAR)
2087ec681f3Smrg      src_pitch /= 4;
2097ec681f3Smrg
2107ec681f3Smrg   assert(cpp <= 4);
2117ec681f3Smrg   crocus_emit_cmd(batch, GENX(XY_SRC_COPY_BLT), xyblt) {
2127ec681f3Smrg      xyblt.RasterOperation = 0xCC;
2137ec681f3Smrg      xyblt.DestinationTilingEnable = dst->surf.tiling != ISL_TILING_LINEAR;
2147ec681f3Smrg      xyblt.SourceTilingEnable = src->surf.tiling != ISL_TILING_LINEAR;
2157ec681f3Smrg      xyblt.SourceBaseAddress = ro_bo(src->bo, src_offset);
2167ec681f3Smrg      xyblt.DestinationBaseAddress = rw_bo(dst->bo, dst_offset);
2177ec681f3Smrg      xyblt.ColorDepth = color_depth_for_cpp(cpp);
2187ec681f3Smrg      xyblt._32bppByteMask = cpp == 4 ? 0x3 : 0x1;
2197ec681f3Smrg      xyblt.DestinationX1Coordinate = dst_x;
2207ec681f3Smrg      xyblt.DestinationY1Coordinate = dst_y;
2217ec681f3Smrg      xyblt.DestinationX2Coordinate = dst_x2;
2227ec681f3Smrg      xyblt.DestinationY2Coordinate = dst_y2;
2237ec681f3Smrg      xyblt.DestinationPitch = dst_pitch;
2247ec681f3Smrg      xyblt.SourceX1Coordinate = src_x;
2257ec681f3Smrg      xyblt.SourceY1Coordinate = src_y;
2267ec681f3Smrg      xyblt.SourcePitch = src_pitch;
2277ec681f3Smrg   };
2287ec681f3Smrg
2297ec681f3Smrg   crocus_emit_mi_flush(batch);
2307ec681f3Smrg   return true;
2317ec681f3Smrg}
2327ec681f3Smrg
2337ec681f3Smrgstatic bool crocus_emit_blt(struct crocus_batch *batch,
2347ec681f3Smrg                            struct crocus_resource *src,
2357ec681f3Smrg                            struct crocus_resource *dst,
2367ec681f3Smrg                            unsigned dst_level,
2377ec681f3Smrg                            unsigned dst_x, unsigned dst_y,
2387ec681f3Smrg                            unsigned dst_z,
2397ec681f3Smrg                            unsigned src_level,
2407ec681f3Smrg                            const struct pipe_box *src_box)
2417ec681f3Smrg{
2427ec681f3Smrg   const struct isl_format_layout *src_fmtl = isl_format_get_layout(src->surf.format);
2437ec681f3Smrg   unsigned src_cpp = src_fmtl->bpb / 8;
2447ec681f3Smrg   const struct isl_format_layout *dst_fmtl = isl_format_get_layout(dst->surf.format);
2457ec681f3Smrg   const unsigned dst_cpp = dst_fmtl->bpb / 8;
2467ec681f3Smrg   uint16_t src_x, src_y;
2477ec681f3Smrg   uint32_t src_image_x, src_image_y, dst_image_x, dst_image_y;
2487ec681f3Smrg   uint32_t src_width = src_box->width, src_height = src_box->height;
2497ec681f3Smrg
2507ec681f3Smrg   /* gen4/5 can't handle Y tiled blits. */
2517ec681f3Smrg   if (src->surf.tiling == ISL_TILING_Y0 || dst->surf.tiling == ISL_TILING_Y0)
2527ec681f3Smrg      return false;
2537ec681f3Smrg
2547ec681f3Smrg   if (src->surf.format != dst->surf.format)
2557ec681f3Smrg      return false;
2567ec681f3Smrg
2577ec681f3Smrg   if (src_cpp != dst_cpp)
2587ec681f3Smrg      return false;
2597ec681f3Smrg
2607ec681f3Smrg   src_x = src_box->x;
2617ec681f3Smrg   src_y = src_box->y;
2627ec681f3Smrg
2637ec681f3Smrg   assert(src_cpp == dst_cpp);
2647ec681f3Smrg
2657ec681f3Smrg   crocus_resource_get_image_offset(src, src_level, src_box->z, &src_image_x,
2667ec681f3Smrg                                    &src_image_y);
2677ec681f3Smrg   if (util_format_is_compressed(src->base.b.format)) {
2687ec681f3Smrg      int bw = util_format_get_blockwidth(src->base.b.format);
2697ec681f3Smrg      int bh = util_format_get_blockheight(src->base.b.format);
2707ec681f3Smrg      assert(src_x % bw == 0);
2717ec681f3Smrg      assert(src_y % bh == 0);
2727ec681f3Smrg      src_x /= (int)bw;
2737ec681f3Smrg      src_y /= (int)bh;
2747ec681f3Smrg      src_width = DIV_ROUND_UP(src_width, (int)bw);
2757ec681f3Smrg      src_height = DIV_ROUND_UP(src_height, (int)bh);
2767ec681f3Smrg   }
2777ec681f3Smrg
2787ec681f3Smrg   crocus_resource_get_image_offset(dst, dst_level, dst_z, &dst_image_x,
2797ec681f3Smrg                                    &dst_image_y);
2807ec681f3Smrg   if (util_format_is_compressed(dst->base.b.format)) {
2817ec681f3Smrg      int bw = util_format_get_blockwidth(dst->base.b.format);
2827ec681f3Smrg      int bh = util_format_get_blockheight(dst->base.b.format);
2837ec681f3Smrg      assert(dst_x % bw == 0);
2847ec681f3Smrg      assert(dst_y % bh == 0);
2857ec681f3Smrg      dst_x /= (int)bw;
2867ec681f3Smrg      dst_y /= (int)bh;
2877ec681f3Smrg   }
2887ec681f3Smrg   src_x += src_image_x;
2897ec681f3Smrg   src_y += src_image_y;
2907ec681f3Smrg   dst_x += dst_image_x;
2917ec681f3Smrg   dst_y += dst_image_y;
2927ec681f3Smrg
2937ec681f3Smrg   /* According to the Ivy Bridge PRM, Vol1 Part4, section 1.2.1.2 (Graphics
2947ec681f3Smrg    * Data Size Limitations):
2957ec681f3Smrg    *
2967ec681f3Smrg    *    The BLT engine is capable of transferring very large quantities of
2977ec681f3Smrg    *    graphics data. Any graphics data read from and written to the
2987ec681f3Smrg    *    destination is permitted to represent a number of pixels that
2997ec681f3Smrg    *    occupies up to 65,536 scan lines and up to 32,768 bytes per scan line
3007ec681f3Smrg    *    at the destination. The maximum number of pixels that may be
3017ec681f3Smrg    *    represented per scan line’s worth of graphics data depends on the
3027ec681f3Smrg    *    color depth.
3037ec681f3Smrg    *
3047ec681f3Smrg    * The blitter's pitch is a signed 16-bit integer, but measured in bytes
3057ec681f3Smrg    * for linear surfaces and DWords for tiled surfaces.  So the maximum
3067ec681f3Smrg    * pitch is 32k linear and 128k tiled.
3077ec681f3Smrg    */
3087ec681f3Smrg   if (crocus_resource_blt_pitch(src) >= 32768 ||
3097ec681f3Smrg       crocus_resource_blt_pitch(dst) >= 32768) {
3107ec681f3Smrg      return false;
3117ec681f3Smrg   }
3127ec681f3Smrg
3137ec681f3Smrg   /* We need to split the blit into chunks that each fit within the blitter's
3147ec681f3Smrg    * restrictions.  We can't use a chunk size of 32768 because we need to
3157ec681f3Smrg    * ensure that src_tile_x + chunk_size fits.  We choose 16384 because it's
3167ec681f3Smrg    * a nice round power of two, big enough that performance won't suffer, and
3177ec681f3Smrg    * small enough to guarantee everything fits.
3187ec681f3Smrg    */
3197ec681f3Smrg   const uint32_t max_chunk_size = 16384;
3207ec681f3Smrg
3217ec681f3Smrg   for (uint32_t chunk_x = 0; chunk_x < src_width; chunk_x += max_chunk_size) {
3227ec681f3Smrg      for (uint32_t chunk_y = 0; chunk_y < src_height; chunk_y += max_chunk_size) {
3237ec681f3Smrg         const uint32_t chunk_w = MIN2(max_chunk_size, src_width - chunk_x);
3247ec681f3Smrg         const uint32_t chunk_h = MIN2(max_chunk_size, src_height - chunk_y);
3257ec681f3Smrg
3267ec681f3Smrg         uint64_t src_offset;
3277ec681f3Smrg         uint32_t src_tile_x, src_tile_y;
3287ec681f3Smrg         ASSERTED uint32_t z_offset_el, array_offset;
3297ec681f3Smrg         isl_tiling_get_intratile_offset_el(src->surf.tiling, src->surf.dim,
3307ec681f3Smrg                                            src->surf.msaa_layout,
3317ec681f3Smrg                                            src_cpp * 8, src->surf.samples,
3327ec681f3Smrg                                            src->surf.row_pitch_B,
3337ec681f3Smrg                                            src->surf.array_pitch_el_rows,
3347ec681f3Smrg                                            src_x + chunk_x, src_y + chunk_y, 0, 0,
3357ec681f3Smrg                                            &src_offset,
3367ec681f3Smrg                                            &src_tile_x, &src_tile_y,
3377ec681f3Smrg                                            &z_offset_el, &array_offset);
3387ec681f3Smrg         assert(z_offset_el == 0);
3397ec681f3Smrg         assert(array_offset == 0);
3407ec681f3Smrg
3417ec681f3Smrg         uint64_t dst_offset;
3427ec681f3Smrg         uint32_t dst_tile_x, dst_tile_y;
3437ec681f3Smrg         isl_tiling_get_intratile_offset_el(dst->surf.tiling, dst->surf.dim,
3447ec681f3Smrg                                            dst->surf.msaa_layout,
3457ec681f3Smrg                                            dst_cpp * 8, dst->surf.samples,
3467ec681f3Smrg                                            dst->surf.row_pitch_B,
3477ec681f3Smrg                                            dst->surf.array_pitch_el_rows,
3487ec681f3Smrg                                            dst_x + chunk_x, dst_y + chunk_y, 0, 0,
3497ec681f3Smrg                                            &dst_offset,
3507ec681f3Smrg                                            &dst_tile_x, &dst_tile_y,
3517ec681f3Smrg                                            &z_offset_el, &array_offset);
3527ec681f3Smrg         assert(z_offset_el == 0);
3537ec681f3Smrg         assert(array_offset == 0);
3547ec681f3Smrg         if (!emit_copy_blt(batch, src, dst,
3557ec681f3Smrg                            src_cpp, src->surf.row_pitch_B,
3567ec681f3Smrg                            src_offset,
3577ec681f3Smrg                            dst->surf.row_pitch_B, dst_offset,
3587ec681f3Smrg                            src_tile_x, src_tile_y,
3597ec681f3Smrg                            dst_tile_x, dst_tile_y,
3607ec681f3Smrg                            chunk_w, chunk_h)) {
3617ec681f3Smrg            return false;
3627ec681f3Smrg         }
3637ec681f3Smrg      }
3647ec681f3Smrg   }
3657ec681f3Smrg
3667ec681f3Smrg   if (util_format_has_alpha1(src->base.b.format) &&
3677ec681f3Smrg       util_format_has_alpha(dst->base.b.format))
3687ec681f3Smrg      blt_set_alpha_to_one(batch, dst, 0, 0, src_width, src_height);
3697ec681f3Smrg   return true;
3707ec681f3Smrg}
3717ec681f3Smrg
3727ec681f3Smrgstatic bool crocus_blit_blt(struct crocus_batch *batch,
3737ec681f3Smrg                            const struct pipe_blit_info *info)
3747ec681f3Smrg{
3757ec681f3Smrg   if (!validate_blit_for_blt(batch, info))
3767ec681f3Smrg      return false;
3777ec681f3Smrg
3787ec681f3Smrg   return crocus_emit_blt(batch,
3797ec681f3Smrg                          (struct crocus_resource *)info->src.resource,
3807ec681f3Smrg                          (struct crocus_resource *)info->dst.resource,
3817ec681f3Smrg                          info->dst.level,
3827ec681f3Smrg                          info->dst.box.x,
3837ec681f3Smrg                          info->dst.box.y,
3847ec681f3Smrg                          info->dst.box.z,
3857ec681f3Smrg                          info->src.level,
3867ec681f3Smrg                          &info->src.box);
3877ec681f3Smrg}
3887ec681f3Smrg
3897ec681f3Smrg
3907ec681f3Smrgstatic bool crocus_copy_region_blt(struct crocus_batch *batch,
3917ec681f3Smrg                                   struct crocus_resource *dst,
3927ec681f3Smrg                                   unsigned dst_level,
3937ec681f3Smrg                                   unsigned dstx, unsigned dsty, unsigned dstz,
3947ec681f3Smrg                                   struct crocus_resource *src,
3957ec681f3Smrg                                   unsigned src_level,
3967ec681f3Smrg                                   const struct pipe_box *src_box)
3977ec681f3Smrg{
3987ec681f3Smrg   if (dst->base.b.target == PIPE_BUFFER || src->base.b.target == PIPE_BUFFER)
3997ec681f3Smrg      return false;
4007ec681f3Smrg   return crocus_emit_blt(batch,
4017ec681f3Smrg                          src,
4027ec681f3Smrg                          dst,
4037ec681f3Smrg                          dst_level,
4047ec681f3Smrg                          dstx, dsty, dstz,
4057ec681f3Smrg                          src_level,
4067ec681f3Smrg                          src_box);
4077ec681f3Smrg}
4087ec681f3Smrg#endif
4097ec681f3Smrg
4107ec681f3Smrgvoid
4117ec681f3SmrggenX(crocus_init_blt)(struct crocus_screen *screen)
4127ec681f3Smrg{
4137ec681f3Smrg#if GFX_VER <= 5
4147ec681f3Smrg   screen->vtbl.blit_blt = crocus_blit_blt;
4157ec681f3Smrg   screen->vtbl.copy_region_blt = crocus_copy_region_blt;
4167ec681f3Smrg#else
4177ec681f3Smrg   screen->vtbl.blit_blt = NULL;
4187ec681f3Smrg   screen->vtbl.copy_region_blt = NULL;
4197ec681f3Smrg#endif
4207ec681f3Smrg}
421