1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright © 2018 Intel Corporation
3bf215546Sopenharmony_ci *
4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
10bf215546Sopenharmony_ci *
11bf215546Sopenharmony_ci * The above copyright notice and this permission notice shall be included
12bf215546Sopenharmony_ci * in all copies or substantial portions of the Software.
13bf215546Sopenharmony_ci *
14bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15bf215546Sopenharmony_ci * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20bf215546Sopenharmony_ci * DEALINGS IN THE SOFTWARE.
21bf215546Sopenharmony_ci */
22bf215546Sopenharmony_ci
23bf215546Sopenharmony_ci/* blt command encoding for gen4/5 */
24bf215546Sopenharmony_ci#include "crocus_context.h"
25bf215546Sopenharmony_ci
26bf215546Sopenharmony_ci#include "crocus_genx_macros.h"
27bf215546Sopenharmony_ci#include "crocus_genx_protos.h"
28bf215546Sopenharmony_ci#include "crocus_resource.h"
29bf215546Sopenharmony_ci
30bf215546Sopenharmony_ci#define FILE_DEBUG_FLAG DEBUG_BLIT
31bf215546Sopenharmony_ci
32bf215546Sopenharmony_ci#if GFX_VER <= 5
33bf215546Sopenharmony_ci
34bf215546Sopenharmony_cistatic uint32_t
35bf215546Sopenharmony_cicolor_depth_for_cpp(int cpp)
36bf215546Sopenharmony_ci{
37bf215546Sopenharmony_ci   switch (cpp) {
38bf215546Sopenharmony_ci   case 4: return COLOR_DEPTH_32bit;
39bf215546Sopenharmony_ci   case 2: return COLOR_DEPTH_565;
40bf215546Sopenharmony_ci   case 1: return COLOR_DEPTH_8bit;
41bf215546Sopenharmony_ci   default:
42bf215546Sopenharmony_ci      unreachable("not reached");
43bf215546Sopenharmony_ci   }
44bf215546Sopenharmony_ci}
45bf215546Sopenharmony_ci
46bf215546Sopenharmony_cistatic void
47bf215546Sopenharmony_ciblt_set_alpha_to_one(struct crocus_batch *batch,
48bf215546Sopenharmony_ci		     struct crocus_resource *dst,
49bf215546Sopenharmony_ci		     int x, int y, int width, int height)
50bf215546Sopenharmony_ci{
51bf215546Sopenharmony_ci   const struct isl_format_layout *fmtl = isl_format_get_layout(dst->surf.format);
52bf215546Sopenharmony_ci   unsigned cpp = fmtl->bpb / 8;
53bf215546Sopenharmony_ci   uint32_t pitch = dst->surf.row_pitch_B;
54bf215546Sopenharmony_ci
55bf215546Sopenharmony_ci   if (dst->surf.tiling != ISL_TILING_LINEAR)
56bf215546Sopenharmony_ci      pitch /= 4;
57bf215546Sopenharmony_ci   /* We need to split the blit into chunks that each fit within the blitter's
58bf215546Sopenharmony_ci    * restrictions.  We can't use a chunk size of 32768 because we need to
59bf215546Sopenharmony_ci    * ensure that src_tile_x + chunk_size fits.  We choose 16384 because it's
60bf215546Sopenharmony_ci    * a nice round power of two, big enough that performance won't suffer, and
61bf215546Sopenharmony_ci    * small enough to guarantee everything fits.
62bf215546Sopenharmony_ci    */
63bf215546Sopenharmony_ci   const uint32_t max_chunk_size = 16384;
64bf215546Sopenharmony_ci
65bf215546Sopenharmony_ci   for (uint32_t chunk_x = 0; chunk_x < width; chunk_x += max_chunk_size) {
66bf215546Sopenharmony_ci      for (uint32_t chunk_y = 0; chunk_y < height; chunk_y += max_chunk_size) {
67bf215546Sopenharmony_ci         const uint32_t chunk_w = MIN2(max_chunk_size, width - chunk_x);
68bf215546Sopenharmony_ci         const uint32_t chunk_h = MIN2(max_chunk_size, height - chunk_y);
69bf215546Sopenharmony_ci         uint32_t tile_x, tile_y;
70bf215546Sopenharmony_ci         uint64_t offset_B;
71bf215546Sopenharmony_ci         ASSERTED uint32_t z_offset_el, array_offset;
72bf215546Sopenharmony_ci         isl_tiling_get_intratile_offset_el(dst->surf.tiling, dst->surf.dim,
73bf215546Sopenharmony_ci                                            dst->surf.msaa_layout,
74bf215546Sopenharmony_ci                                            cpp * 8, dst->surf.samples,
75bf215546Sopenharmony_ci                                            dst->surf.row_pitch_B,
76bf215546Sopenharmony_ci                                            dst->surf.array_pitch_el_rows,
77bf215546Sopenharmony_ci                                            chunk_x, chunk_y, 0, 0,
78bf215546Sopenharmony_ci                                            &offset_B,
79bf215546Sopenharmony_ci                                            &tile_x, &tile_y,
80bf215546Sopenharmony_ci                                            &z_offset_el, &array_offset);
81bf215546Sopenharmony_ci         assert(z_offset_el == 0);
82bf215546Sopenharmony_ci         assert(array_offset == 0);
83bf215546Sopenharmony_ci	 crocus_emit_cmd(batch, GENX(XY_COLOR_BLT), xyblt) {
84bf215546Sopenharmony_ci            xyblt.TilingEnable = dst->surf.tiling != ISL_TILING_LINEAR;
85bf215546Sopenharmony_ci            xyblt.ColorDepth = color_depth_for_cpp(cpp);
86bf215546Sopenharmony_ci            xyblt.RasterOperation = 0xF0;
87bf215546Sopenharmony_ci            xyblt.DestinationPitch = pitch;
88bf215546Sopenharmony_ci            xyblt._32bppByteMask = 2;
89bf215546Sopenharmony_ci            xyblt.DestinationBaseAddress = rw_bo(dst->bo, offset_B);
90bf215546Sopenharmony_ci            xyblt.DestinationX1Coordinate = tile_x;
91bf215546Sopenharmony_ci            xyblt.DestinationY1Coordinate = tile_y;
92bf215546Sopenharmony_ci            xyblt.DestinationX2Coordinate = tile_x + chunk_w;
93bf215546Sopenharmony_ci            xyblt.DestinationY2Coordinate = tile_y + chunk_h;
94bf215546Sopenharmony_ci            xyblt.SolidPatternColor = 0xffffffff;
95bf215546Sopenharmony_ci	 }
96bf215546Sopenharmony_ci      }
97bf215546Sopenharmony_ci   }
98bf215546Sopenharmony_ci}
99bf215546Sopenharmony_ci
100bf215546Sopenharmony_cistatic bool validate_blit_for_blt(struct crocus_batch *batch,
101bf215546Sopenharmony_ci                                  const struct pipe_blit_info *info)
102bf215546Sopenharmony_ci{
103bf215546Sopenharmony_ci   /* If the source and destination are the same size with no mirroring,
104bf215546Sopenharmony_ci    * the rectangles are within the size of the texture and there is no
105bf215546Sopenharmony_ci    * scissor, then we can probably use the blit engine.
106bf215546Sopenharmony_ci    */
107bf215546Sopenharmony_ci   if (info->dst.box.width != info->src.box.width ||
108bf215546Sopenharmony_ci       info->dst.box.height != info->src.box.height)
109bf215546Sopenharmony_ci      return false;
110bf215546Sopenharmony_ci
111bf215546Sopenharmony_ci   if (info->scissor_enable)
112bf215546Sopenharmony_ci      return false;
113bf215546Sopenharmony_ci
114bf215546Sopenharmony_ci   if (info->dst.box.height < 0 || info->src.box.height < 0)
115bf215546Sopenharmony_ci      return false;
116bf215546Sopenharmony_ci
117bf215546Sopenharmony_ci   if (info->dst.box.depth > 1 || info->src.box.depth > 1)
118bf215546Sopenharmony_ci      return false;
119bf215546Sopenharmony_ci
120bf215546Sopenharmony_ci   const struct util_format_description *desc =
121bf215546Sopenharmony_ci      util_format_description(info->src.format);
122bf215546Sopenharmony_ci   int i = util_format_get_first_non_void_channel(info->src.format);
123bf215546Sopenharmony_ci   if (i == -1)
124bf215546Sopenharmony_ci      return false;
125bf215546Sopenharmony_ci
126bf215546Sopenharmony_ci   /* can't do the alpha to 1 setting for these. */
127bf215546Sopenharmony_ci   if ((util_format_has_alpha1(info->src.format) &&
128bf215546Sopenharmony_ci        util_format_has_alpha(info->dst.format) &&
129bf215546Sopenharmony_ci        desc->channel[i].size > 8))
130bf215546Sopenharmony_ci      return false;
131bf215546Sopenharmony_ci   return true;
132bf215546Sopenharmony_ci}
133bf215546Sopenharmony_ci
134bf215546Sopenharmony_cistatic inline int crocus_resource_blt_pitch(struct crocus_resource *res)
135bf215546Sopenharmony_ci{
136bf215546Sopenharmony_ci   int pitch = res->surf.row_pitch_B;
137bf215546Sopenharmony_ci   if (res->surf.tiling != ISL_TILING_LINEAR)
138bf215546Sopenharmony_ci      pitch /= 4;
139bf215546Sopenharmony_ci   return pitch;
140bf215546Sopenharmony_ci}
141bf215546Sopenharmony_ci
142bf215546Sopenharmony_ci
143bf215546Sopenharmony_cistatic bool emit_copy_blt(struct crocus_batch *batch,
144bf215546Sopenharmony_ci                          struct crocus_resource *src,
145bf215546Sopenharmony_ci                          struct crocus_resource *dst,
146bf215546Sopenharmony_ci                          unsigned cpp,
147bf215546Sopenharmony_ci                          int32_t src_pitch,
148bf215546Sopenharmony_ci                          unsigned src_offset,
149bf215546Sopenharmony_ci                          int32_t dst_pitch,
150bf215546Sopenharmony_ci                          unsigned dst_offset,
151bf215546Sopenharmony_ci                          uint16_t src_x, uint16_t src_y,
152bf215546Sopenharmony_ci                          uint16_t dst_x, uint16_t dst_y,
153bf215546Sopenharmony_ci                          uint16_t w, uint16_t h)
154bf215546Sopenharmony_ci
155bf215546Sopenharmony_ci{
156bf215546Sopenharmony_ci   uint32_t src_tile_w, src_tile_h;
157bf215546Sopenharmony_ci   uint32_t dst_tile_w, dst_tile_h;
158bf215546Sopenharmony_ci   int dst_y2 = dst_y + h;
159bf215546Sopenharmony_ci   int dst_x2 = dst_x + w;
160bf215546Sopenharmony_ci
161bf215546Sopenharmony_ci   DBG("%s src:buf(%p)/%d+%d %d,%d dst:buf(%p)/%d+%d %d,%d sz:%dx%d\n",
162bf215546Sopenharmony_ci       __func__,
163bf215546Sopenharmony_ci       src, src_pitch, src_offset, src_x, src_y,
164bf215546Sopenharmony_ci       dst, dst_pitch, dst_offset, dst_x, dst_y, w, h);
165bf215546Sopenharmony_ci
166bf215546Sopenharmony_ci   isl_get_tile_dims(src->surf.tiling, cpp, &src_tile_w, &src_tile_h);
167bf215546Sopenharmony_ci   isl_get_tile_dims(dst->surf.tiling, cpp, &dst_tile_w, &dst_tile_h);
168bf215546Sopenharmony_ci
169bf215546Sopenharmony_ci   /* For Tiled surfaces, the pitch has to be a multiple of the Tile width
170bf215546Sopenharmony_ci    * (X direction width of the Tile). This is ensured while allocating the
171bf215546Sopenharmony_ci    * buffer object.
172bf215546Sopenharmony_ci    */
173bf215546Sopenharmony_ci   assert(src->surf.tiling == ISL_TILING_LINEAR || (src_pitch % src_tile_w) == 0);
174bf215546Sopenharmony_ci   assert(dst->surf.tiling == ISL_TILING_LINEAR || (dst_pitch % dst_tile_w) == 0);
175bf215546Sopenharmony_ci
176bf215546Sopenharmony_ci   /* For big formats (such as floating point), do the copy using 16 or
177bf215546Sopenharmony_ci    * 32bpp and multiply the coordinates.
178bf215546Sopenharmony_ci    */
179bf215546Sopenharmony_ci   if (cpp > 4) {
180bf215546Sopenharmony_ci      if (cpp % 4 == 2) {
181bf215546Sopenharmony_ci         dst_x *= cpp / 2;
182bf215546Sopenharmony_ci         dst_x2 *= cpp / 2;
183bf215546Sopenharmony_ci         src_x *= cpp / 2;
184bf215546Sopenharmony_ci         cpp = 2;
185bf215546Sopenharmony_ci      } else {
186bf215546Sopenharmony_ci         assert(cpp % 4 == 0);
187bf215546Sopenharmony_ci         dst_x *= cpp / 4;
188bf215546Sopenharmony_ci         dst_x2 *= cpp / 4;
189bf215546Sopenharmony_ci         src_x *= cpp / 4;
190bf215546Sopenharmony_ci         cpp = 4;
191bf215546Sopenharmony_ci      }
192bf215546Sopenharmony_ci   }
193bf215546Sopenharmony_ci
194bf215546Sopenharmony_ci   /* Blit pitch must be dword-aligned.  Otherwise, the hardware appears to drop
195bf215546Sopenharmony_ci    * the low bits.  Offsets must be naturally aligned.
196bf215546Sopenharmony_ci    */
197bf215546Sopenharmony_ci   if (src_pitch % 4 != 0 || src_offset % cpp != 0 ||
198bf215546Sopenharmony_ci       dst_pitch % 4 != 0 || dst_offset % cpp != 0)
199bf215546Sopenharmony_ci     return false;
200bf215546Sopenharmony_ci
201bf215546Sopenharmony_ci   /* For tiled source and destination, pitch value should be specified
202bf215546Sopenharmony_ci    * as a number of Dwords.
203bf215546Sopenharmony_ci    */
204bf215546Sopenharmony_ci   if (dst->surf.tiling != ISL_TILING_LINEAR)
205bf215546Sopenharmony_ci      dst_pitch /= 4;
206bf215546Sopenharmony_ci
207bf215546Sopenharmony_ci   if (src->surf.tiling != ISL_TILING_LINEAR)
208bf215546Sopenharmony_ci      src_pitch /= 4;
209bf215546Sopenharmony_ci
210bf215546Sopenharmony_ci   assert(cpp <= 4);
211bf215546Sopenharmony_ci   crocus_emit_cmd(batch, GENX(XY_SRC_COPY_BLT), xyblt) {
212bf215546Sopenharmony_ci      xyblt.RasterOperation = 0xCC;
213bf215546Sopenharmony_ci      xyblt.DestinationTilingEnable = dst->surf.tiling != ISL_TILING_LINEAR;
214bf215546Sopenharmony_ci      xyblt.SourceTilingEnable = src->surf.tiling != ISL_TILING_LINEAR;
215bf215546Sopenharmony_ci      xyblt.SourceBaseAddress = ro_bo(src->bo, src_offset);
216bf215546Sopenharmony_ci      xyblt.DestinationBaseAddress = rw_bo(dst->bo, dst_offset);
217bf215546Sopenharmony_ci      xyblt.ColorDepth = color_depth_for_cpp(cpp);
218bf215546Sopenharmony_ci      xyblt._32bppByteMask = cpp == 4 ? 0x3 : 0x1;
219bf215546Sopenharmony_ci      xyblt.DestinationX1Coordinate = dst_x;
220bf215546Sopenharmony_ci      xyblt.DestinationY1Coordinate = dst_y;
221bf215546Sopenharmony_ci      xyblt.DestinationX2Coordinate = dst_x2;
222bf215546Sopenharmony_ci      xyblt.DestinationY2Coordinate = dst_y2;
223bf215546Sopenharmony_ci      xyblt.DestinationPitch = dst_pitch;
224bf215546Sopenharmony_ci      xyblt.SourceX1Coordinate = src_x;
225bf215546Sopenharmony_ci      xyblt.SourceY1Coordinate = src_y;
226bf215546Sopenharmony_ci      xyblt.SourcePitch = src_pitch;
227bf215546Sopenharmony_ci   };
228bf215546Sopenharmony_ci
229bf215546Sopenharmony_ci   crocus_emit_mi_flush(batch);
230bf215546Sopenharmony_ci   return true;
231bf215546Sopenharmony_ci}
232bf215546Sopenharmony_ci
233bf215546Sopenharmony_cistatic bool crocus_emit_blt(struct crocus_batch *batch,
234bf215546Sopenharmony_ci                            struct crocus_resource *src,
235bf215546Sopenharmony_ci                            struct crocus_resource *dst,
236bf215546Sopenharmony_ci                            unsigned dst_level,
237bf215546Sopenharmony_ci                            unsigned dst_x, unsigned dst_y,
238bf215546Sopenharmony_ci                            unsigned dst_z,
239bf215546Sopenharmony_ci                            unsigned src_level,
240bf215546Sopenharmony_ci                            const struct pipe_box *src_box)
241bf215546Sopenharmony_ci{
242bf215546Sopenharmony_ci   const struct isl_format_layout *src_fmtl = isl_format_get_layout(src->surf.format);
243bf215546Sopenharmony_ci   unsigned src_cpp = src_fmtl->bpb / 8;
244bf215546Sopenharmony_ci   const struct isl_format_layout *dst_fmtl = isl_format_get_layout(dst->surf.format);
245bf215546Sopenharmony_ci   const unsigned dst_cpp = dst_fmtl->bpb / 8;
246bf215546Sopenharmony_ci   uint16_t src_x, src_y;
247bf215546Sopenharmony_ci   uint32_t src_image_x, src_image_y, dst_image_x, dst_image_y;
248bf215546Sopenharmony_ci   uint32_t src_width = src_box->width, src_height = src_box->height;
249bf215546Sopenharmony_ci
250bf215546Sopenharmony_ci   /* gen4/5 can't handle Y tiled blits. */
251bf215546Sopenharmony_ci   if (src->surf.tiling == ISL_TILING_Y0 || dst->surf.tiling == ISL_TILING_Y0)
252bf215546Sopenharmony_ci      return false;
253bf215546Sopenharmony_ci
254bf215546Sopenharmony_ci   if (src->surf.format != dst->surf.format)
255bf215546Sopenharmony_ci      return false;
256bf215546Sopenharmony_ci
257bf215546Sopenharmony_ci   if (src_cpp != dst_cpp)
258bf215546Sopenharmony_ci      return false;
259bf215546Sopenharmony_ci
260bf215546Sopenharmony_ci   src_x = src_box->x;
261bf215546Sopenharmony_ci   src_y = src_box->y;
262bf215546Sopenharmony_ci
263bf215546Sopenharmony_ci   assert(src_cpp == dst_cpp);
264bf215546Sopenharmony_ci
265bf215546Sopenharmony_ci   crocus_resource_get_image_offset(src, src_level, src_box->z, &src_image_x,
266bf215546Sopenharmony_ci                                    &src_image_y);
267bf215546Sopenharmony_ci   if (util_format_is_compressed(src->base.b.format)) {
268bf215546Sopenharmony_ci      int bw = util_format_get_blockwidth(src->base.b.format);
269bf215546Sopenharmony_ci      int bh = util_format_get_blockheight(src->base.b.format);
270bf215546Sopenharmony_ci      assert(src_x % bw == 0);
271bf215546Sopenharmony_ci      assert(src_y % bh == 0);
272bf215546Sopenharmony_ci      src_x /= (int)bw;
273bf215546Sopenharmony_ci      src_y /= (int)bh;
274bf215546Sopenharmony_ci      src_width = DIV_ROUND_UP(src_width, (int)bw);
275bf215546Sopenharmony_ci      src_height = DIV_ROUND_UP(src_height, (int)bh);
276bf215546Sopenharmony_ci   }
277bf215546Sopenharmony_ci
278bf215546Sopenharmony_ci   crocus_resource_get_image_offset(dst, dst_level, dst_z, &dst_image_x,
279bf215546Sopenharmony_ci                                    &dst_image_y);
280bf215546Sopenharmony_ci   if (util_format_is_compressed(dst->base.b.format)) {
281bf215546Sopenharmony_ci      int bw = util_format_get_blockwidth(dst->base.b.format);
282bf215546Sopenharmony_ci      int bh = util_format_get_blockheight(dst->base.b.format);
283bf215546Sopenharmony_ci      assert(dst_x % bw == 0);
284bf215546Sopenharmony_ci      assert(dst_y % bh == 0);
285bf215546Sopenharmony_ci      dst_x /= (int)bw;
286bf215546Sopenharmony_ci      dst_y /= (int)bh;
287bf215546Sopenharmony_ci   }
288bf215546Sopenharmony_ci   src_x += src_image_x;
289bf215546Sopenharmony_ci   src_y += src_image_y;
290bf215546Sopenharmony_ci   dst_x += dst_image_x;
291bf215546Sopenharmony_ci   dst_y += dst_image_y;
292bf215546Sopenharmony_ci
293bf215546Sopenharmony_ci   /* According to the Ivy Bridge PRM, Vol1 Part4, section 1.2.1.2 (Graphics
294bf215546Sopenharmony_ci    * Data Size Limitations):
295bf215546Sopenharmony_ci    *
296bf215546Sopenharmony_ci    *    The BLT engine is capable of transferring very large quantities of
297bf215546Sopenharmony_ci    *    graphics data. Any graphics data read from and written to the
298bf215546Sopenharmony_ci    *    destination is permitted to represent a number of pixels that
299bf215546Sopenharmony_ci    *    occupies up to 65,536 scan lines and up to 32,768 bytes per scan line
300bf215546Sopenharmony_ci    *    at the destination. The maximum number of pixels that may be
301bf215546Sopenharmony_ci    *    represented per scan line’s worth of graphics data depends on the
302bf215546Sopenharmony_ci    *    color depth.
303bf215546Sopenharmony_ci    *
304bf215546Sopenharmony_ci    * The blitter's pitch is a signed 16-bit integer, but measured in bytes
305bf215546Sopenharmony_ci    * for linear surfaces and DWords for tiled surfaces.  So the maximum
306bf215546Sopenharmony_ci    * pitch is 32k linear and 128k tiled.
307bf215546Sopenharmony_ci    */
308bf215546Sopenharmony_ci   if (crocus_resource_blt_pitch(src) >= 32768 ||
309bf215546Sopenharmony_ci       crocus_resource_blt_pitch(dst) >= 32768) {
310bf215546Sopenharmony_ci      return false;
311bf215546Sopenharmony_ci   }
312bf215546Sopenharmony_ci
313bf215546Sopenharmony_ci   /* We need to split the blit into chunks that each fit within the blitter's
314bf215546Sopenharmony_ci    * restrictions.  We can't use a chunk size of 32768 because we need to
315bf215546Sopenharmony_ci    * ensure that src_tile_x + chunk_size fits.  We choose 16384 because it's
316bf215546Sopenharmony_ci    * a nice round power of two, big enough that performance won't suffer, and
317bf215546Sopenharmony_ci    * small enough to guarantee everything fits.
318bf215546Sopenharmony_ci    */
319bf215546Sopenharmony_ci   const uint32_t max_chunk_size = 16384;
320bf215546Sopenharmony_ci
321bf215546Sopenharmony_ci   for (uint32_t chunk_x = 0; chunk_x < src_width; chunk_x += max_chunk_size) {
322bf215546Sopenharmony_ci      for (uint32_t chunk_y = 0; chunk_y < src_height; chunk_y += max_chunk_size) {
323bf215546Sopenharmony_ci         const uint32_t chunk_w = MIN2(max_chunk_size, src_width - chunk_x);
324bf215546Sopenharmony_ci         const uint32_t chunk_h = MIN2(max_chunk_size, src_height - chunk_y);
325bf215546Sopenharmony_ci
326bf215546Sopenharmony_ci         uint64_t src_offset;
327bf215546Sopenharmony_ci         uint32_t src_tile_x, src_tile_y;
328bf215546Sopenharmony_ci         ASSERTED uint32_t z_offset_el, array_offset;
329bf215546Sopenharmony_ci         isl_tiling_get_intratile_offset_el(src->surf.tiling, src->surf.dim,
330bf215546Sopenharmony_ci                                            src->surf.msaa_layout,
331bf215546Sopenharmony_ci                                            src_cpp * 8, src->surf.samples,
332bf215546Sopenharmony_ci                                            src->surf.row_pitch_B,
333bf215546Sopenharmony_ci                                            src->surf.array_pitch_el_rows,
334bf215546Sopenharmony_ci                                            src_x + chunk_x, src_y + chunk_y, 0, 0,
335bf215546Sopenharmony_ci                                            &src_offset,
336bf215546Sopenharmony_ci                                            &src_tile_x, &src_tile_y,
337bf215546Sopenharmony_ci                                            &z_offset_el, &array_offset);
338bf215546Sopenharmony_ci         assert(z_offset_el == 0);
339bf215546Sopenharmony_ci         assert(array_offset == 0);
340bf215546Sopenharmony_ci
341bf215546Sopenharmony_ci         uint64_t dst_offset;
342bf215546Sopenharmony_ci         uint32_t dst_tile_x, dst_tile_y;
343bf215546Sopenharmony_ci         isl_tiling_get_intratile_offset_el(dst->surf.tiling, dst->surf.dim,
344bf215546Sopenharmony_ci                                            dst->surf.msaa_layout,
345bf215546Sopenharmony_ci                                            dst_cpp * 8, dst->surf.samples,
346bf215546Sopenharmony_ci                                            dst->surf.row_pitch_B,
347bf215546Sopenharmony_ci                                            dst->surf.array_pitch_el_rows,
348bf215546Sopenharmony_ci                                            dst_x + chunk_x, dst_y + chunk_y, 0, 0,
349bf215546Sopenharmony_ci                                            &dst_offset,
350bf215546Sopenharmony_ci                                            &dst_tile_x, &dst_tile_y,
351bf215546Sopenharmony_ci                                            &z_offset_el, &array_offset);
352bf215546Sopenharmony_ci         assert(z_offset_el == 0);
353bf215546Sopenharmony_ci         assert(array_offset == 0);
354bf215546Sopenharmony_ci         if (!emit_copy_blt(batch, src, dst,
355bf215546Sopenharmony_ci                            src_cpp, src->surf.row_pitch_B,
356bf215546Sopenharmony_ci                            src_offset,
357bf215546Sopenharmony_ci                            dst->surf.row_pitch_B, dst_offset,
358bf215546Sopenharmony_ci                            src_tile_x, src_tile_y,
359bf215546Sopenharmony_ci                            dst_tile_x, dst_tile_y,
360bf215546Sopenharmony_ci                            chunk_w, chunk_h)) {
361bf215546Sopenharmony_ci            return false;
362bf215546Sopenharmony_ci         }
363bf215546Sopenharmony_ci      }
364bf215546Sopenharmony_ci   }
365bf215546Sopenharmony_ci
366bf215546Sopenharmony_ci   if (util_format_has_alpha1(src->base.b.format) &&
367bf215546Sopenharmony_ci       util_format_has_alpha(dst->base.b.format))
368bf215546Sopenharmony_ci      blt_set_alpha_to_one(batch, dst, 0, 0, src_width, src_height);
369bf215546Sopenharmony_ci   return true;
370bf215546Sopenharmony_ci}
371bf215546Sopenharmony_ci
372bf215546Sopenharmony_cistatic bool crocus_blit_blt(struct crocus_batch *batch,
373bf215546Sopenharmony_ci                            const struct pipe_blit_info *info)
374bf215546Sopenharmony_ci{
375bf215546Sopenharmony_ci   if (!validate_blit_for_blt(batch, info))
376bf215546Sopenharmony_ci      return false;
377bf215546Sopenharmony_ci
378bf215546Sopenharmony_ci   return crocus_emit_blt(batch,
379bf215546Sopenharmony_ci                          (struct crocus_resource *)info->src.resource,
380bf215546Sopenharmony_ci                          (struct crocus_resource *)info->dst.resource,
381bf215546Sopenharmony_ci                          info->dst.level,
382bf215546Sopenharmony_ci                          info->dst.box.x,
383bf215546Sopenharmony_ci                          info->dst.box.y,
384bf215546Sopenharmony_ci                          info->dst.box.z,
385bf215546Sopenharmony_ci                          info->src.level,
386bf215546Sopenharmony_ci                          &info->src.box);
387bf215546Sopenharmony_ci}
388bf215546Sopenharmony_ci
389bf215546Sopenharmony_ci
390bf215546Sopenharmony_cistatic bool crocus_copy_region_blt(struct crocus_batch *batch,
391bf215546Sopenharmony_ci                                   struct crocus_resource *dst,
392bf215546Sopenharmony_ci                                   unsigned dst_level,
393bf215546Sopenharmony_ci                                   unsigned dstx, unsigned dsty, unsigned dstz,
394bf215546Sopenharmony_ci                                   struct crocus_resource *src,
395bf215546Sopenharmony_ci                                   unsigned src_level,
396bf215546Sopenharmony_ci                                   const struct pipe_box *src_box)
397bf215546Sopenharmony_ci{
398bf215546Sopenharmony_ci   if (dst->base.b.target == PIPE_BUFFER || src->base.b.target == PIPE_BUFFER)
399bf215546Sopenharmony_ci      return false;
400bf215546Sopenharmony_ci   return crocus_emit_blt(batch,
401bf215546Sopenharmony_ci                          src,
402bf215546Sopenharmony_ci                          dst,
403bf215546Sopenharmony_ci                          dst_level,
404bf215546Sopenharmony_ci                          dstx, dsty, dstz,
405bf215546Sopenharmony_ci                          src_level,
406bf215546Sopenharmony_ci                          src_box);
407bf215546Sopenharmony_ci}
408bf215546Sopenharmony_ci#endif
409bf215546Sopenharmony_ci
410bf215546Sopenharmony_civoid
411bf215546Sopenharmony_cigenX(crocus_init_blt)(struct crocus_screen *screen)
412bf215546Sopenharmony_ci{
413bf215546Sopenharmony_ci#if GFX_VER <= 5
414bf215546Sopenharmony_ci   screen->vtbl.blit_blt = crocus_blit_blt;
415bf215546Sopenharmony_ci   screen->vtbl.copy_region_blt = crocus_copy_region_blt;
416bf215546Sopenharmony_ci#else
417bf215546Sopenharmony_ci   screen->vtbl.blit_blt = NULL;
418bf215546Sopenharmony_ci   screen->vtbl.copy_region_blt = NULL;
419bf215546Sopenharmony_ci#endif
420bf215546Sopenharmony_ci}
421