Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  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 <olv@lunarg.com>
  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. }
  574.