Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5564 serge 1
/*
2
 * Mesa 3-D graphics library
3
 *
4
 * Copyright (C) 2013 LunarG, Inc.
5
 *
6
 * Permission is hereby granted, free of charge, to any person obtaining a
7
 * copy of this software and associated documentation files (the "Software"),
8
 * to deal in the Software without restriction, including without limitation
9
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10
 * and/or sell copies of the Software, and to permit persons to whom the
11
 * Software is furnished to do so, subject to the following conditions:
12
 *
13
 * The above copyright notice and this permission notice shall be included
14
 * in all copies or substantial portions of the Software.
15
 *
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22
 * DEALINGS IN THE SOFTWARE.
23
 *
24
 * Authors:
25
 *    Chia-I Wu 
26
 */
27
 
28
#include "genhw/genhw.h"
29
#include "core/ilo_builder_mi.h"
30
#include "core/ilo_builder_blt.h"
31
#include "util/u_pack_color.h"
32
 
33
#include "ilo_context.h"
34
#include "ilo_cp.h"
35
#include "ilo_blit.h"
36
#include "ilo_resource.h"
37
#include "ilo_blitter.h"
38
 
39
static uint32_t
40
ilo_blitter_blt_begin(struct ilo_blitter *blitter, int max_cmd_size,
41
                      struct intel_bo *dst,
42
                      enum gen_surface_tiling dst_tiling,
43
                      struct intel_bo *src,
44
                      enum gen_surface_tiling src_tiling)
45
{
46
   struct ilo_cp *cp = blitter->ilo->cp;
47
   struct intel_bo *aper_check[2];
48
   int count;
49
   uint32_t swctrl;
50
 
51
   /* change owner */
52
   ilo_cp_set_owner(cp, INTEL_RING_BLT, NULL);
53
 
54
   /* check aperture space */
55
   aper_check[0] = dst;
56
   count = 1;
57
 
58
   if (src) {
59
      aper_check[1] = src;
60
      count++;
61
   }
62
 
63
   if (!ilo_builder_validate(&cp->builder, count, aper_check))
64
      ilo_cp_submit(cp, "out of aperture");
65
 
66
   /* set BCS_SWCTRL */
67
   swctrl = 0x0;
68
 
69
   assert(dst_tiling == GEN6_TILING_NONE ||
70
          dst_tiling == GEN6_TILING_X ||
71
          dst_tiling == GEN6_TILING_Y);
72
   assert(src_tiling == GEN6_TILING_NONE ||
73
          src_tiling == GEN6_TILING_X ||
74
          src_tiling == GEN6_TILING_Y);
75
 
76
   if (dst_tiling == GEN6_TILING_Y) {
77
      swctrl |= GEN6_REG_BCS_SWCTRL_DST_TILING_Y << 16 |
78
                GEN6_REG_BCS_SWCTRL_DST_TILING_Y;
79
   }
80
 
81
   if (src && src_tiling == GEN6_TILING_Y) {
82
      swctrl |= GEN6_REG_BCS_SWCTRL_SRC_TILING_Y << 16 |
83
                GEN6_REG_BCS_SWCTRL_SRC_TILING_Y;
84
   }
85
 
86
   /*
87
    * Most clients expect BLT engine to be stateless.  If we have to set
88
    * BCS_SWCTRL to a non-default value, we have to set it back in the same
89
    * batch buffer.
90
    */
91
   if (swctrl)
92
      max_cmd_size += (4 + 3) * 2;
93
 
94
   if (ilo_cp_space(cp) < max_cmd_size) {
95
      ilo_cp_submit(cp, "out of space");
96
      assert(ilo_cp_space(cp) >= max_cmd_size);
97
   }
98
 
99
   if (swctrl) {
100
      /*
101
       * From the Ivy Bridge PRM, volume 1 part 4, page 133:
102
       *
103
       *     "SW is required to flush the HW before changing the polarity of
104
       *      this bit (Tile Y Destination/Source)."
105
       */
106
      gen6_MI_FLUSH_DW(&cp->builder);
107
      gen6_MI_LOAD_REGISTER_IMM(&cp->builder, GEN6_REG_BCS_SWCTRL, swctrl);
108
 
109
      swctrl &= ~(GEN6_REG_BCS_SWCTRL_DST_TILING_Y |
110
                  GEN6_REG_BCS_SWCTRL_SRC_TILING_Y);
111
   }
112
 
113
   return swctrl;
114
}
115
 
116
static void
117
ilo_blitter_blt_end(struct ilo_blitter *blitter, uint32_t swctrl)
118
{
119
   struct ilo_builder *builder = &blitter->ilo->cp->builder;
120
 
121
   /* set BCS_SWCTRL back */
122
   if (swctrl) {
123
      gen6_MI_FLUSH_DW(builder);
124
      gen6_MI_LOAD_REGISTER_IMM(builder, GEN6_REG_BCS_SWCTRL, swctrl);
125
   }
126
}
127
 
128
static bool
129
buf_clear_region(struct ilo_blitter *blitter,
130
                 struct ilo_buffer *buf, unsigned offset,
131
                 uint32_t val, unsigned size,
132
                 enum gen6_blt_mask value_mask,
133
                 enum gen6_blt_mask write_mask)
134
{
135
   const uint8_t rop = 0xf0; /* PATCOPY */
136
   const int cpp = gen6_blt_translate_value_cpp(value_mask);
137
   struct ilo_builder *builder = &blitter->ilo->cp->builder;
138
   struct gen6_blt_bo dst;
139
 
140
   if (offset % cpp || size % cpp)
141
      return false;
142
 
143
   dst.bo = buf->bo;
144
   dst.offset = offset;
145
 
146
   ilo_blitter_blt_begin(blitter, GEN6_COLOR_BLT__SIZE *
147
         (1 + size / 32764 / gen6_blt_max_scanlines),
148
         dst.bo, GEN6_TILING_NONE, NULL, GEN6_TILING_NONE);
149
 
150
   while (size) {
151
      unsigned width, height;
152
 
153
      width = size;
154
      height = 1;
155
 
156
      if (width > gen6_blt_max_bytes_per_scanline) {
157
         /* less than INT16_MAX and dword-aligned */
158
         width = 32764;
159
         height = size / width;
160
         if (height > gen6_blt_max_scanlines)
161
            height = gen6_blt_max_scanlines;
162
 
163
         dst.pitch = width;
164
      } else {
165
         dst.pitch = 0;
166
      }
167
 
168
      gen6_COLOR_BLT(builder, &dst, val,
169
            width, height, rop, value_mask, write_mask);
170
 
171
      dst.offset += dst.pitch * height;
172
      size -= width * height;
173
   }
174
 
175
   ilo_blitter_blt_end(blitter, 0);
176
 
177
   return true;
178
}
179
 
180
static bool
181
buf_copy_region(struct ilo_blitter *blitter,
182
                struct ilo_buffer *dst_buf, unsigned dst_offset,
183
                struct ilo_buffer *src_buf, unsigned src_offset,
184
                unsigned size)
185
{
186
   const uint8_t rop = 0xcc; /* SRCCOPY */
187
   struct ilo_builder *builder = &blitter->ilo->cp->builder;
188
   struct gen6_blt_bo dst, src;
189
 
190
   dst.bo = dst_buf->bo;
191
   dst.offset = dst_offset;
192
   dst.pitch = 0;
193
 
194
   src.bo = src_buf->bo;
195
   src.offset = src_offset;
196
   src.pitch = 0;
197
 
198
   ilo_blitter_blt_begin(blitter, GEN6_SRC_COPY_BLT__SIZE *
199
         (1 + size / 32764 / gen6_blt_max_scanlines),
200
         dst_buf->bo, GEN6_TILING_NONE, src_buf->bo, GEN6_TILING_NONE);
201
 
202
   while (size) {
203
      unsigned width, height;
204
 
205
      width = size;
206
      height = 1;
207
 
208
      if (width > gen6_blt_max_bytes_per_scanline) {
209
         /* less than INT16_MAX and dword-aligned */
210
         width = 32764;
211
         height = size / width;
212
         if (height > gen6_blt_max_scanlines)
213
            height = gen6_blt_max_scanlines;
214
 
215
         dst.pitch = width;
216
         src.pitch = width;
217
      } else {
218
         dst.pitch = 0;
219
         src.pitch = 0;
220
      }
221
 
222
      gen6_SRC_COPY_BLT(builder, &dst, &src,
223
            width, height, rop, GEN6_BLT_MASK_8, GEN6_BLT_MASK_8);
224
 
225
      dst.offset += dst.pitch * height;
226
      src.offset += src.pitch * height;
227
      size -= width * height;
228
   }
229
 
230
   ilo_blitter_blt_end(blitter, 0);
231
 
232
   return true;
233
}
234
 
235
static bool
236
tex_clear_region(struct ilo_blitter *blitter,
237
                 struct ilo_texture *dst_tex, unsigned dst_level,
238
                 const struct pipe_box *dst_box,
239
                 uint32_t val,
240
                 enum gen6_blt_mask value_mask,
241
                 enum gen6_blt_mask write_mask)
242
{
243
   const int cpp = gen6_blt_translate_value_cpp(value_mask);
244
   const unsigned max_extent = 32767; /* INT16_MAX */
245
   const uint8_t rop = 0xf0; /* PATCOPY */
246
   struct ilo_builder *builder = &blitter->ilo->cp->builder;
247
   struct gen6_blt_xy_bo dst;
248
   uint32_t swctrl;
249
   int slice;
250
 
251
   /* no W-tiling nor separate stencil support */
252
   if (dst_tex->image.tiling == GEN8_TILING_W || dst_tex->separate_s8)
253
      return false;
254
 
255
   if (dst_tex->image.bo_stride > max_extent)
256
      return false;
257
 
258
   if (dst_box->width * cpp > gen6_blt_max_bytes_per_scanline)
259
      return false;
260
 
261
   dst.bo = dst_tex->image.bo;
262
   dst.offset = 0;
263
   dst.pitch = dst_tex->image.bo_stride;
264
   dst.tiling = dst_tex->image.tiling;
265
 
266
   swctrl = ilo_blitter_blt_begin(blitter,
267
         GEN6_XY_COLOR_BLT__SIZE * dst_box->depth,
268
         dst_tex->image.bo, dst_tex->image.tiling, NULL, GEN6_TILING_NONE);
269
 
270
   for (slice = 0; slice < dst_box->depth; slice++) {
271
      unsigned x, y;
272
 
273
      ilo_image_get_slice_pos(&dst_tex->image,
274
            dst_level, dst_box->z + slice, &x, &y);
275
 
276
      dst.x = x + dst_box->x;
277
      dst.y = y + dst_box->y;
278
 
279
      if (dst.x + dst_box->width > max_extent ||
280
          dst.y + dst_box->height > max_extent)
281
         break;
282
 
283
      gen6_XY_COLOR_BLT(builder, &dst, val,
284
            dst_box->width, dst_box->height, rop, value_mask, write_mask);
285
   }
286
 
287
   ilo_blitter_blt_end(blitter, swctrl);
288
 
289
   return (slice == dst_box->depth);
290
}
291
 
292
static bool
293
tex_copy_region(struct ilo_blitter *blitter,
294
                struct ilo_texture *dst_tex,
295
                unsigned dst_level,
296
                unsigned dst_x, unsigned dst_y, unsigned dst_z,
297
                struct ilo_texture *src_tex,
298
                unsigned src_level,
299
                const struct pipe_box *src_box)
300
{
301
   const struct util_format_description *desc =
302
      util_format_description(dst_tex->image.format);
303
   const unsigned max_extent = 32767; /* INT16_MAX */
304
   const uint8_t rop = 0xcc; /* SRCCOPY */
305
   struct ilo_builder *builder = &blitter->ilo->cp->builder;
306
   enum gen6_blt_mask mask;
307
   struct gen6_blt_xy_bo dst, src;
308
   uint32_t swctrl;
309
   int cpp, xscale, slice;
310
 
311
   /* no W-tiling nor separate stencil support */
312
   if (dst_tex->image.tiling == GEN8_TILING_W || dst_tex->separate_s8 ||
313
       src_tex->image.tiling == GEN8_TILING_W || src_tex->separate_s8)
314
      return false;
315
 
316
   if (dst_tex->image.bo_stride > max_extent ||
317
       src_tex->image.bo_stride > max_extent)
318
      return false;
319
 
320
   cpp = desc->block.bits / 8;
321
   xscale = 1;
322
 
323
   /* accommodate for larger cpp */
324
   if (cpp > 4) {
325
      if (cpp % 2 == 1)
326
         return false;
327
 
328
      cpp = (cpp % 4 == 0) ? 4 : 2;
329
      xscale = (desc->block.bits / 8) / cpp;
330
   }
331
 
332
   if (src_box->width * cpp * xscale > gen6_blt_max_bytes_per_scanline)
333
      return false;
334
 
335
   switch (cpp) {
336
   case 1:
337
      mask = GEN6_BLT_MASK_8;
338
      break;
339
   case 2:
340
      mask = GEN6_BLT_MASK_16;
341
      break;
342
   case 4:
343
      mask = GEN6_BLT_MASK_32;
344
      break;
345
   default:
346
      return false;
347
      break;
348
   }
349
 
350
   dst.bo = dst_tex->image.bo;
351
   dst.offset = 0;
352
   dst.pitch = dst_tex->image.bo_stride;
353
   dst.tiling = dst_tex->image.tiling;
354
 
355
   src.bo = src_tex->image.bo;
356
   src.offset = 0;
357
   src.pitch = src_tex->image.bo_stride;
358
   src.tiling = src_tex->image.tiling;
359
 
360
   swctrl = ilo_blitter_blt_begin(blitter,
361
         GEN6_XY_SRC_COPY_BLT__SIZE * src_box->depth,
362
         dst.bo, dst.tiling, src.bo, src.tiling);
363
 
364
   for (slice = 0; slice < src_box->depth; slice++) {
365
      unsigned dx, dy, sx, sy, width, height;
366
 
367
      ilo_image_get_slice_pos(&dst_tex->image,
368
            dst_level, dst_z + slice, &dx, &dy);
369
      ilo_image_get_slice_pos(&src_tex->image,
370
            src_level, src_box->z + slice, &sx, &sy);
371
 
372
      dst.x = (dx + dst_x) * xscale;
373
      dst.y = dy + dst_y;
374
      src.x = (sx + src_box->x) * xscale;
375
      src.y = sy + src_box->y;
376
      width = src_box->width * xscale;
377
      height = src_box->height;
378
 
379
      /* in blocks */
380
      dst.x /= desc->block.width;
381
      dst.y /= desc->block.height;
382
      src.x /= desc->block.width;
383
      src.y /= desc->block.height;
384
      width /= desc->block.width;
385
      height /= desc->block.height;
386
 
387
      if (src.x + width > max_extent || src.y + height > max_extent ||
388
          dst.x + width > max_extent || dst.y + height > max_extent)
389
         break;
390
 
391
      gen6_XY_SRC_COPY_BLT(builder, &dst, &src,
392
            width, height, rop, mask, mask);
393
   }
394
 
395
   ilo_blitter_blt_end(blitter, swctrl);
396
 
397
   return (slice == src_box->depth);
398
}
399
 
400
bool
401
ilo_blitter_blt_copy_resource(struct ilo_blitter *blitter,
402
                              struct pipe_resource *dst, unsigned dst_level,
403
                              unsigned dst_x, unsigned dst_y, unsigned dst_z,
404
                              struct pipe_resource *src, unsigned src_level,
405
                              const struct pipe_box *src_box)
406
{
407
   bool success;
408
 
409
   ilo_blit_resolve_slices(blitter->ilo, src, src_level,
410
         src_box->z, src_box->depth, ILO_TEXTURE_BLT_READ);
411
   ilo_blit_resolve_slices(blitter->ilo, dst, dst_level,
412
         dst_z, src_box->depth, ILO_TEXTURE_BLT_WRITE);
413
 
414
   if (dst->target == PIPE_BUFFER && src->target == PIPE_BUFFER) {
415
      const unsigned dst_offset = dst_x;
416
      const unsigned src_offset = src_box->x;
417
      const unsigned size = src_box->width;
418
 
419
      assert(dst_level == 0 && dst_y == 0 && dst_z == 0);
420
      assert(src_level == 0 &&
421
             src_box->y == 0 &&
422
             src_box->z == 0 &&
423
             src_box->height == 1 &&
424
             src_box->depth == 1);
425
 
426
      success = buf_copy_region(blitter,
427
            ilo_buffer(dst), dst_offset, ilo_buffer(src), src_offset, size);
428
   }
429
   else if (dst->target != PIPE_BUFFER && src->target != PIPE_BUFFER) {
430
      success = tex_copy_region(blitter,
431
            ilo_texture(dst), dst_level, dst_x, dst_y, dst_z,
432
            ilo_texture(src), src_level, src_box);
433
   }
434
   else {
435
      success = false;
436
   }
437
 
438
   return success;
439
}
440
 
441
bool
442
ilo_blitter_blt_clear_rt(struct ilo_blitter *blitter,
443
                         struct pipe_surface *rt,
444
                         const union pipe_color_union *color,
445
                         unsigned x, unsigned y,
446
                         unsigned width, unsigned height)
447
{
448
   const int cpp = util_format_get_blocksize(rt->format);
449
   enum gen6_blt_mask mask;
450
   union util_color packed;
451
   bool success;
452
 
453
   if (ilo_skip_rendering(blitter->ilo))
454
      return true;
455
 
456
   switch (cpp) {
457
   case 1:
458
      mask = GEN6_BLT_MASK_8;
459
      break;
460
   case 2:
461
      mask = GEN6_BLT_MASK_16;
462
      break;
463
   case 4:
464
      mask = GEN6_BLT_MASK_32;
465
      break;
466
   default:
467
      return false;
468
      break;
469
   }
470
 
471
   if (util_format_is_pure_integer(rt->format) ||
472
       util_format_is_compressed(rt->format))
473
      return false;
474
 
475
   ilo_blit_resolve_surface(blitter->ilo, rt, ILO_TEXTURE_BLT_WRITE);
476
 
477
   util_pack_color(color->f, rt->format, &packed);
478
 
479
   if (rt->texture->target == PIPE_BUFFER) {
480
      unsigned offset, end, size;
481
 
482
      assert(y == 0 && height == 1);
483
 
484
      offset = (rt->u.buf.first_element + x) * cpp;
485
      end = (rt->u.buf.last_element + 1) * cpp;
486
 
487
      size = width * cpp;
488
      if (offset + size > end)
489
         size = end - offset;
490
 
491
      success = buf_clear_region(blitter, ilo_buffer(rt->texture),
492
            offset, packed.ui[0], size, mask, mask);
493
   }
494
   else {
495
      struct pipe_box box;
496
 
497
      u_box_3d(x, y, rt->u.tex.first_layer, width, height,
498
            rt->u.tex.last_layer - rt->u.tex.first_layer + 1, &box);
499
 
500
      success = tex_clear_region(blitter, ilo_texture(rt->texture),
501
            rt->u.tex.level, &box, packed.ui[0], mask, mask);
502
   }
503
 
504
   return success;
505
}
506
 
507
bool
508
ilo_blitter_blt_clear_zs(struct ilo_blitter *blitter,
509
                         struct pipe_surface *zs,
510
                         unsigned clear_flags,
511
                         double depth, unsigned stencil,
512
                         unsigned x, unsigned y,
513
                         unsigned width, unsigned height)
514
{
515
   enum gen6_blt_mask value_mask, write_mask;
516
   struct pipe_box box;
517
   uint32_t val;
518
 
519
   if (ilo_skip_rendering(blitter->ilo))
520
      return true;
521
 
522
   switch (zs->format) {
523
   case PIPE_FORMAT_Z16_UNORM:
524
      if (!(clear_flags & PIPE_CLEAR_DEPTH))
525
         return true;
526
 
527
      value_mask = GEN6_BLT_MASK_16;
528
      write_mask = GEN6_BLT_MASK_16;
529
      break;
530
   case PIPE_FORMAT_Z32_FLOAT:
531
      if (!(clear_flags & PIPE_CLEAR_DEPTH))
532
         return true;
533
 
534
      value_mask = GEN6_BLT_MASK_32;
535
      write_mask = GEN6_BLT_MASK_32;
536
      break;
537
   case PIPE_FORMAT_Z24X8_UNORM:
538
      if (!(clear_flags & PIPE_CLEAR_DEPTH))
539
         return true;
540
 
541
      value_mask = GEN6_BLT_MASK_32;
542
      write_mask = GEN6_BLT_MASK_32_LO;
543
      break;
544
   case PIPE_FORMAT_Z24_UNORM_S8_UINT:
545
      if (!(clear_flags & PIPE_CLEAR_DEPTHSTENCIL))
546
         return true;
547
 
548
      value_mask = GEN6_BLT_MASK_32;
549
 
550
      if ((clear_flags & PIPE_CLEAR_DEPTHSTENCIL) == PIPE_CLEAR_DEPTHSTENCIL)
551
         write_mask = GEN6_BLT_MASK_32;
552
      else if (clear_flags & PIPE_CLEAR_DEPTH)
553
         write_mask = GEN6_BLT_MASK_32_LO;
554
      else
555
         write_mask = GEN6_BLT_MASK_32_HI;
556
      break;
557
   default:
558
      return false;
559
      break;
560
   }
561
 
562
   ilo_blit_resolve_surface(blitter->ilo, zs, ILO_TEXTURE_BLT_WRITE);
563
 
564
   val = util_pack_z_stencil(zs->format, depth, stencil);
565
 
566
   u_box_3d(x, y, zs->u.tex.first_layer, width, height,
567
         zs->u.tex.last_layer - zs->u.tex.first_layer + 1, &box);
568
 
569
   assert(zs->texture->target != PIPE_BUFFER);
570
 
571
   return tex_clear_region(blitter, ilo_texture(zs->texture),
572
         zs->u.tex.level, &box, val, value_mask, write_mask);
573
}