Subversion Repositories Kolibri OS

Rev

Go to most recent revision | 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 "util/u_pack_color.h"
  29. #include "intel_reg.h"
  30.  
  31. #include "ilo_3d.h"
  32. #include "ilo_context.h"
  33. #include "ilo_cp.h"
  34. #include "ilo_resource.h"
  35. #include "ilo_blitter.h"
  36.  
  37. #ifndef COLOR_BLT_CMD
  38. #define COLOR_BLT_CMD (CMD_2D | (0x40 << 22))
  39. #endif
  40.  
  41. #ifndef SRC_COPY_BLT_CMD
  42. #define SRC_COPY_BLT_CMD (CMD_2D | (0x43 << 22))
  43. #endif
  44.  
  45. enum gen6_blt_mask {
  46.    GEN6_BLT_MASK_8,
  47.    GEN6_BLT_MASK_16,
  48.    GEN6_BLT_MASK_32,
  49.    GEN6_BLT_MASK_32_LO,
  50.    GEN6_BLT_MASK_32_HI,
  51. };
  52.  
  53. /*
  54.  * From the Sandy Bridge PRM, volume 1 part 5, page 7:
  55.  *
  56.  *     "The BLT engine is capable of transferring very large quantities of
  57.  *      graphics data. Any graphics data read from and written to the
  58.  *      destination is permitted to represent a number of pixels that occupies
  59.  *      up to 65,536 scan lines and up to 32,768 bytes per scan line at the
  60.  *      destination. The maximum number of pixels that may be represented per
  61.  *      scan line's worth of graphics data depends on the color depth."
  62.  */
  63. static const int gen6_max_bytes_per_scanline = 32768;
  64. static const int gen6_max_scanlines = 65536;
  65.  
  66. static void
  67. gen6_emit_MI_FLUSH_DW(struct ilo_dev_info *dev, struct ilo_cp *cp)
  68. {
  69.    const uint8_t cmd_len = 4;
  70.  
  71.    ilo_cp_begin(cp, cmd_len);
  72.    ilo_cp_write(cp, MI_FLUSH_DW | (cmd_len - 2));
  73.    ilo_cp_write(cp, 0);
  74.    ilo_cp_write(cp, 0);
  75.    ilo_cp_write(cp, 0);
  76.    ilo_cp_end(cp);
  77. }
  78.  
  79. static void
  80. gen6_emit_MI_LOAD_REGISTER_IMM(struct ilo_dev_info *dev,
  81.                                uint32_t reg, uint32_t val,
  82.                                struct ilo_cp *cp)
  83. {
  84.    const uint8_t cmd_len = 3;
  85.  
  86.    ilo_cp_begin(cp, cmd_len);
  87.    ilo_cp_write(cp, MI_LOAD_REGISTER_IMM | (cmd_len - 2));
  88.    ilo_cp_write(cp, reg);
  89.    ilo_cp_write(cp, val);
  90.    ilo_cp_end(cp);
  91. }
  92.  
  93. static uint32_t
  94. gen6_translate_blt_value_mask(enum gen6_blt_mask value_mask)
  95. {
  96.    switch (value_mask) {
  97.    case GEN6_BLT_MASK_8:  return BR13_8;
  98.    case GEN6_BLT_MASK_16: return BR13_565;
  99.    default:               return BR13_8888;
  100.    }
  101. }
  102.  
  103. static uint32_t
  104. gen6_translate_blt_write_mask(enum gen6_blt_mask write_mask)
  105. {
  106.    switch (write_mask) {
  107.    case GEN6_BLT_MASK_32:    return XY_BLT_WRITE_RGB |
  108.                                     XY_BLT_WRITE_ALPHA;
  109.    case GEN6_BLT_MASK_32_LO: return XY_BLT_WRITE_RGB;
  110.    case GEN6_BLT_MASK_32_HI: return XY_BLT_WRITE_ALPHA;
  111.    default:                  return 0;
  112.    }
  113. }
  114.  
  115. static uint32_t
  116. gen6_translate_blt_cpp(enum gen6_blt_mask mask)
  117. {
  118.    switch (mask) {
  119.    case GEN6_BLT_MASK_8:  return 1;
  120.    case GEN6_BLT_MASK_16: return 2;
  121.    default:               return 4;
  122.    }
  123. }
  124.  
  125. static void
  126. gen6_emit_COLOR_BLT(struct ilo_dev_info *dev,
  127.                     struct intel_bo *dst_bo,
  128.                     int16_t dst_pitch, uint32_t dst_offset,
  129.                     uint16_t width, uint16_t height,
  130.                     uint32_t pattern, uint8_t rop,
  131.                     enum gen6_blt_mask value_mask,
  132.                     enum gen6_blt_mask write_mask,
  133.                     struct ilo_cp *cp)
  134. {
  135.    const uint8_t cmd_len = 5;
  136.    const int cpp = gen6_translate_blt_cpp(value_mask);
  137.    uint32_t dw0, dw1;
  138.  
  139.    dw0 = COLOR_BLT_CMD |
  140.          gen6_translate_blt_write_mask(write_mask) |
  141.          (cmd_len - 2);
  142.  
  143.    assert(width < gen6_max_bytes_per_scanline);
  144.    assert(height < gen6_max_scanlines);
  145.    /* offsets are naturally aligned and pitches are dword-aligned */
  146.    assert(dst_offset % cpp == 0 && dst_pitch % 4 == 0);
  147.  
  148.    dw1 = rop << 16 |
  149.          gen6_translate_blt_value_mask(value_mask) |
  150.          dst_pitch;
  151.  
  152.    ilo_cp_begin(cp, cmd_len);
  153.    ilo_cp_write(cp, dw0);
  154.    ilo_cp_write(cp, dw1);
  155.    ilo_cp_write(cp, height << 16 | width);
  156.    ilo_cp_write_bo(cp, dst_offset, dst_bo, INTEL_DOMAIN_RENDER,
  157.                                            INTEL_DOMAIN_RENDER);
  158.    ilo_cp_write(cp, pattern);
  159.    ilo_cp_end(cp);
  160. }
  161.  
  162. static void
  163. gen6_emit_XY_COLOR_BLT(struct ilo_dev_info *dev,
  164.                        struct intel_bo *dst_bo,
  165.                        enum intel_tiling_mode dst_tiling,
  166.                        int16_t dst_pitch, uint32_t dst_offset,
  167.                        int16_t x1, int16_t y1, int16_t x2, int16_t y2,
  168.                        uint32_t pattern, uint8_t rop,
  169.                        enum gen6_blt_mask value_mask,
  170.                        enum gen6_blt_mask write_mask,
  171.                        struct ilo_cp *cp)
  172. {
  173.    const uint8_t cmd_len = 6;
  174.    const int cpp = gen6_translate_blt_cpp(value_mask);
  175.    int dst_align, dst_pitch_shift;
  176.    uint32_t dw0, dw1;
  177.  
  178.    dw0 = XY_COLOR_BLT_CMD |
  179.          gen6_translate_blt_write_mask(write_mask) |
  180.          (cmd_len - 2);
  181.  
  182.    if (dst_tiling == INTEL_TILING_NONE) {
  183.       dst_align = 4;
  184.       dst_pitch_shift = 0;
  185.    }
  186.    else {
  187.       dw0 |= XY_DST_TILED;
  188.  
  189.       dst_align = (dst_tiling == INTEL_TILING_Y) ? 128 : 512;
  190.       /* in dwords when tiled */
  191.       dst_pitch_shift = 2;
  192.    }
  193.  
  194.    assert((x2 - x1) * cpp < gen6_max_bytes_per_scanline);
  195.    assert(y2 - y1 < gen6_max_scanlines);
  196.    assert(dst_offset % dst_align == 0 && dst_pitch % dst_align == 0);
  197.  
  198.    dw1 = rop << 16 |
  199.          gen6_translate_blt_value_mask(value_mask) |
  200.          dst_pitch >> dst_pitch_shift;
  201.  
  202.    ilo_cp_begin(cp, cmd_len);
  203.    ilo_cp_write(cp, dw0);
  204.    ilo_cp_write(cp, dw1);
  205.    ilo_cp_write(cp, y1 << 16 | x1);
  206.    ilo_cp_write(cp, y2 << 16 | x2);
  207.    ilo_cp_write_bo(cp, dst_offset, dst_bo,
  208.                    INTEL_DOMAIN_RENDER, INTEL_DOMAIN_RENDER);
  209.    ilo_cp_write(cp, pattern);
  210.    ilo_cp_end(cp);
  211. }
  212.  
  213. static void
  214. gen6_emit_SRC_COPY_BLT(struct ilo_dev_info *dev,
  215.                        struct intel_bo *dst_bo,
  216.                        int16_t dst_pitch, uint32_t dst_offset,
  217.                        uint16_t width, uint16_t height,
  218.                        struct intel_bo *src_bo,
  219.                        int16_t src_pitch, uint32_t src_offset,
  220.                        bool dir_rtl, uint8_t rop,
  221.                        enum gen6_blt_mask value_mask,
  222.                        enum gen6_blt_mask write_mask,
  223.                        struct ilo_cp *cp)
  224. {
  225.    const uint8_t cmd_len = 6;
  226.    const int cpp = gen6_translate_blt_cpp(value_mask);
  227.    uint32_t dw0, dw1;
  228.  
  229.    dw0 = SRC_COPY_BLT_CMD |
  230.          gen6_translate_blt_write_mask(write_mask) |
  231.          (cmd_len - 2);
  232.  
  233.    assert(width < gen6_max_bytes_per_scanline);
  234.    assert(height < gen6_max_scanlines);
  235.    /* offsets are naturally aligned and pitches are dword-aligned */
  236.    assert(dst_offset % cpp == 0 && dst_pitch % 4 == 0);
  237.    assert(src_offset % cpp == 0 && src_pitch % 4 == 0);
  238.  
  239.    dw1 = rop << 16 |
  240.          gen6_translate_blt_value_mask(value_mask) |
  241.          dst_pitch;
  242.  
  243.    if (dir_rtl)
  244.       dw1 |= 1 << 30;
  245.  
  246.    ilo_cp_begin(cp, cmd_len);
  247.    ilo_cp_write(cp, dw0);
  248.    ilo_cp_write(cp, dw1);
  249.    ilo_cp_write(cp, height << 16 | width);
  250.    ilo_cp_write_bo(cp, dst_offset, dst_bo, INTEL_DOMAIN_RENDER,
  251.                                            INTEL_DOMAIN_RENDER);
  252.    ilo_cp_write(cp, src_pitch);
  253.    ilo_cp_write_bo(cp, src_offset, src_bo, INTEL_DOMAIN_RENDER, 0);
  254.    ilo_cp_end(cp);
  255. }
  256.  
  257. static void
  258. gen6_emit_XY_SRC_COPY_BLT(struct ilo_dev_info *dev,
  259.                           struct intel_bo *dst_bo,
  260.                           enum intel_tiling_mode dst_tiling,
  261.                           int16_t dst_pitch, uint32_t dst_offset,
  262.                           int16_t x1, int16_t y1, int16_t x2, int16_t y2,
  263.                           struct intel_bo *src_bo,
  264.                           enum intel_tiling_mode src_tiling,
  265.                           int16_t src_pitch, uint32_t src_offset,
  266.                           int16_t src_x, int16_t src_y, uint8_t rop,
  267.                           enum gen6_blt_mask value_mask,
  268.                           enum gen6_blt_mask write_mask,
  269.                           struct ilo_cp *cp)
  270. {
  271.    const uint8_t cmd_len = 8;
  272.    const int cpp = gen6_translate_blt_cpp(value_mask);
  273.    int dst_align, dst_pitch_shift;
  274.    int src_align, src_pitch_shift;
  275.    uint32_t dw0, dw1;
  276.  
  277.    dw0 = XY_SRC_COPY_BLT_CMD |
  278.          gen6_translate_blt_write_mask(write_mask) |
  279.          (cmd_len - 2);
  280.  
  281.    if (dst_tiling == INTEL_TILING_NONE) {
  282.       dst_align = 4;
  283.       dst_pitch_shift = 0;
  284.    }
  285.    else {
  286.       dw0 |= XY_DST_TILED;
  287.  
  288.       dst_align = (dst_tiling == INTEL_TILING_Y) ? 128 : 512;
  289.       /* in dwords when tiled */
  290.       dst_pitch_shift = 2;
  291.    }
  292.  
  293.    if (src_tiling == INTEL_TILING_NONE) {
  294.       src_align = 4;
  295.       src_pitch_shift = 0;
  296.    }
  297.    else {
  298.       dw0 |= XY_SRC_TILED;
  299.  
  300.       src_align = (src_tiling == INTEL_TILING_Y) ? 128 : 512;
  301.       /* in dwords when tiled */
  302.       src_pitch_shift = 2;
  303.    }
  304.  
  305.    assert((x2 - x1) * cpp < gen6_max_bytes_per_scanline);
  306.    assert(y2 - y1 < gen6_max_scanlines);
  307.    assert(dst_offset % dst_align == 0 && dst_pitch % dst_align == 0);
  308.    assert(src_offset % src_align == 0 && src_pitch % src_align == 0);
  309.  
  310.    dw1 = rop << 16 |
  311.          gen6_translate_blt_value_mask(value_mask) |
  312.          dst_pitch >> dst_pitch_shift;
  313.  
  314.    ilo_cp_begin(cp, cmd_len);
  315.    ilo_cp_write(cp, dw0);
  316.    ilo_cp_write(cp, dw1);
  317.    ilo_cp_write(cp, y1 << 16 | x1);
  318.    ilo_cp_write(cp, y2 << 16 | x2);
  319.    ilo_cp_write_bo(cp, dst_offset, dst_bo, INTEL_DOMAIN_RENDER,
  320.                                            INTEL_DOMAIN_RENDER);
  321.    ilo_cp_write(cp, src_y << 16 | src_x);
  322.    ilo_cp_write(cp, src_pitch >> src_pitch_shift);
  323.    ilo_cp_write_bo(cp, src_offset, src_bo, INTEL_DOMAIN_RENDER, 0);
  324.    ilo_cp_end(cp);
  325. }
  326.  
  327. static uint32_t
  328. ilo_blitter_blt_begin(struct ilo_blitter *blitter, int max_cmd_size,
  329.                       struct intel_bo *dst, enum intel_tiling_mode dst_tiling,
  330.                       struct intel_bo *src, enum intel_tiling_mode src_tiling)
  331. {
  332.    struct ilo_context *ilo = blitter->ilo;
  333.    struct intel_bo *aper_check[3];
  334.    int count;
  335.    uint32_t swctrl;
  336.  
  337.    /* change ring */
  338.    ilo_cp_set_ring(ilo->cp, ILO_CP_RING_BLT);
  339.    ilo_cp_set_owner(ilo->cp, NULL, 0);
  340.  
  341.    /* check aperture space */
  342.    aper_check[0] = ilo->cp->bo;
  343.    aper_check[1] = dst;
  344.    count = 2;
  345.  
  346.    if (src) {
  347.       aper_check[2] = src;
  348.       count++;
  349.    }
  350.  
  351.    if (intel_winsys_check_aperture_space(ilo->winsys, aper_check, count))
  352.       ilo_cp_flush(ilo->cp);
  353.  
  354.    /* set BCS_SWCTRL */
  355.    swctrl = 0x0;
  356.  
  357.    if (dst_tiling == INTEL_TILING_Y) {
  358.       swctrl |= BCS_SWCTRL_DST_Y << 16 |
  359.                 BCS_SWCTRL_DST_Y;
  360.    }
  361.  
  362.    if (src && src_tiling == INTEL_TILING_Y) {
  363.       swctrl |= BCS_SWCTRL_SRC_Y << 16 |
  364.                 BCS_SWCTRL_SRC_Y;
  365.    }
  366.  
  367.    if (swctrl) {
  368.       /*
  369.        * Most clients expect BLT engine to be stateless.  If we have to set
  370.        * BCS_SWCTRL to a non-default value, we have to set it back in the same
  371.        * batch buffer.
  372.        */
  373.       if (ilo_cp_space(ilo->cp) < (4 + 3) * 2 + max_cmd_size)
  374.          ilo_cp_flush(ilo->cp);
  375.  
  376.       ilo_cp_assert_no_implicit_flush(ilo->cp, true);
  377.  
  378.       /*
  379.        * From the Ivy Bridge PRM, volume 1 part 4, page 133:
  380.        *
  381.        *     "SW is required to flush the HW before changing the polarity of
  382.        *      this bit (Tile Y Destination/Source)."
  383.        */
  384.       gen6_emit_MI_FLUSH_DW(ilo->dev, ilo->cp);
  385.       gen6_emit_MI_LOAD_REGISTER_IMM(ilo->dev, BCS_SWCTRL, swctrl, ilo->cp);
  386.  
  387.       swctrl &= ~(BCS_SWCTRL_DST_Y | BCS_SWCTRL_SRC_Y);
  388.    }
  389.  
  390.    return swctrl;
  391. }
  392.  
  393. static void
  394. ilo_blitter_blt_end(struct ilo_blitter *blitter, uint32_t swctrl)
  395. {
  396.    struct ilo_context *ilo = blitter->ilo;
  397.  
  398.    /* set BCS_SWCTRL back */
  399.    if (swctrl) {
  400.       gen6_emit_MI_FLUSH_DW(ilo->dev, ilo->cp);
  401.       gen6_emit_MI_LOAD_REGISTER_IMM(ilo->dev, BCS_SWCTRL, swctrl, ilo->cp);
  402.  
  403.       ilo_cp_assert_no_implicit_flush(ilo->cp, false);
  404.    }
  405. }
  406.  
  407. static bool
  408. buf_clear_region(struct ilo_blitter *blitter,
  409.                  struct ilo_buffer *dst,
  410.                  unsigned dst_offset, unsigned dst_size,
  411.                  uint32_t val,
  412.                  enum gen6_blt_mask value_mask,
  413.                  enum gen6_blt_mask write_mask)
  414. {
  415.    const uint8_t rop = 0xf0; /* PATCOPY */
  416.    const int cpp = gen6_translate_blt_cpp(value_mask);
  417.    struct ilo_context *ilo = blitter->ilo;
  418.    unsigned offset = 0;
  419.  
  420.    if (dst_offset % cpp || dst_size % cpp)
  421.       return false;
  422.  
  423.    ilo_blitter_blt_begin(blitter, 0,
  424.          dst->bo, INTEL_TILING_NONE, NULL, INTEL_TILING_NONE);
  425.  
  426.    while (dst_size) {
  427.       unsigned width, height;
  428.       int16_t pitch;
  429.  
  430.       width = dst_size;
  431.       height = 1;
  432.       pitch = 0;
  433.  
  434.       if (width > gen6_max_bytes_per_scanline) {
  435.          /* less than INT16_MAX and dword-aligned */
  436.          pitch = 32764;
  437.  
  438.          width = pitch;
  439.          height = dst_size / width;
  440.          if (height > gen6_max_scanlines)
  441.             height = gen6_max_scanlines;
  442.       }
  443.  
  444.       gen6_emit_COLOR_BLT(ilo->dev, dst->bo, pitch, dst_offset + offset,
  445.             width, height, val, rop, value_mask, write_mask, ilo->cp);
  446.  
  447.       offset += pitch * height;
  448.       dst_size -= width * height;
  449.    }
  450.  
  451.    ilo_blitter_blt_end(blitter, 0);
  452.  
  453.    return true;
  454. }
  455.  
  456. static bool
  457. buf_copy_region(struct ilo_blitter *blitter,
  458.                 struct ilo_buffer *dst, unsigned dst_offset,
  459.                 struct ilo_buffer *src, unsigned src_offset,
  460.                 unsigned size)
  461. {
  462.    const uint8_t rop = 0xcc; /* SRCCOPY */
  463.    struct ilo_context *ilo = blitter->ilo;
  464.    unsigned offset = 0;
  465.  
  466.    ilo_blitter_blt_begin(blitter, 0,
  467.          dst->bo, INTEL_TILING_NONE, src->bo, INTEL_TILING_NONE);
  468.  
  469.    while (size) {
  470.       unsigned width, height;
  471.       int16_t pitch;
  472.  
  473.       width = size;
  474.       height = 1;
  475.       pitch = 0;
  476.  
  477.       if (width > gen6_max_bytes_per_scanline) {
  478.          /* less than INT16_MAX and dword-aligned */
  479.          pitch = 32764;
  480.  
  481.          width = pitch;
  482.          height = size / width;
  483.          if (height > gen6_max_scanlines)
  484.             height = gen6_max_scanlines;
  485.       }
  486.  
  487.       gen6_emit_SRC_COPY_BLT(ilo->dev,
  488.             dst->bo, pitch, dst_offset + offset,
  489.             width, height,
  490.             src->bo, pitch, src_offset + offset,
  491.             false, rop, GEN6_BLT_MASK_8, GEN6_BLT_MASK_8,
  492.             ilo->cp);
  493.  
  494.       offset += pitch * height;
  495.       size -= width * height;
  496.    }
  497.  
  498.    ilo_blitter_blt_end(blitter, 0);
  499.  
  500.    return true;
  501. }
  502.  
  503. static bool
  504. tex_clear_region(struct ilo_blitter *blitter,
  505.                  struct ilo_texture *dst, unsigned dst_level,
  506.                  const struct pipe_box *dst_box,
  507.                  uint32_t val,
  508.                  enum gen6_blt_mask value_mask,
  509.                  enum gen6_blt_mask write_mask)
  510. {
  511.    const int cpp = gen6_translate_blt_cpp(value_mask);
  512.    const unsigned max_extent = 32767; /* INT16_MAX */
  513.    const uint8_t rop = 0xf0; /* PATCOPY */
  514.    struct ilo_context *ilo = blitter->ilo;
  515.    uint32_t swctrl;
  516.    int slice;
  517.  
  518.    /* no W-tiling support */
  519.    if (dst->separate_s8)
  520.       return false;
  521.  
  522.    if (dst->bo_stride > max_extent)
  523.       return false;
  524.  
  525.    swctrl = ilo_blitter_blt_begin(blitter, dst_box->depth * 6,
  526.          dst->bo, dst->tiling, NULL, INTEL_TILING_NONE);
  527.  
  528.    for (slice = 0; slice < dst_box->depth; slice++) {
  529.       const struct ilo_texture_slice *dst_slice =
  530.          &dst->slice_offsets[dst_level][dst_box->z + slice];
  531.       unsigned x1, y1, x2, y2;
  532.  
  533.       x1 = dst_slice->x + dst_box->x;
  534.       y1 = dst_slice->y + dst_box->y;
  535.       x2 = x1 + dst_box->width;
  536.       y2 = y1 + dst_box->height;
  537.  
  538.       if (x2 > max_extent || y2 > max_extent ||
  539.           (x2 - x1) * cpp > gen6_max_bytes_per_scanline)
  540.          break;
  541.  
  542.       gen6_emit_XY_COLOR_BLT(ilo->dev,
  543.             dst->bo, dst->tiling, dst->bo_stride, 0,
  544.             x1, y1, x2, y2, val, rop, value_mask, write_mask,
  545.             ilo->cp);
  546.    }
  547.  
  548.    ilo_blitter_blt_end(blitter, swctrl);
  549.  
  550.    return (slice == dst_box->depth);
  551. }
  552.  
  553. static bool
  554. tex_copy_region(struct ilo_blitter *blitter,
  555.                 struct ilo_texture *dst,
  556.                 unsigned dst_level,
  557.                 unsigned dst_x, unsigned dst_y, unsigned dst_z,
  558.                 struct ilo_texture *src,
  559.                 unsigned src_level,
  560.                 const struct pipe_box *src_box)
  561. {
  562.    const struct util_format_description *desc =
  563.       util_format_description(dst->bo_format);
  564.    const unsigned max_extent = 32767; /* INT16_MAX */
  565.    const uint8_t rop = 0xcc; /* SRCCOPY */
  566.    struct ilo_context *ilo = blitter->ilo;
  567.    enum gen6_blt_mask mask;
  568.    uint32_t swctrl;
  569.    int cpp, xscale, slice;
  570.  
  571.    /* no W-tiling support */
  572.    if (dst->separate_s8 || src->separate_s8)
  573.       return false;
  574.  
  575.    if (dst->bo_stride > max_extent || src->bo_stride > max_extent)
  576.       return false;
  577.  
  578.    cpp = desc->block.bits / 8;
  579.    xscale = 1;
  580.  
  581.    /* accommodate for larger cpp */
  582.    if (cpp > 4) {
  583.       if (cpp % 2 == 1)
  584.          return false;
  585.  
  586.       cpp = (cpp % 4 == 0) ? 4 : 2;
  587.       xscale = (desc->block.bits / 8) / cpp;
  588.    }
  589.  
  590.    switch (cpp) {
  591.    case 1:
  592.       mask = GEN6_BLT_MASK_8;
  593.       break;
  594.    case 2:
  595.       mask = GEN6_BLT_MASK_16;
  596.       break;
  597.    case 4:
  598.       mask = GEN6_BLT_MASK_32;
  599.       break;
  600.    default:
  601.       return false;
  602.       break;
  603.    }
  604.  
  605.    swctrl = ilo_blitter_blt_begin(blitter, src_box->depth * 8,
  606.          dst->bo, dst->tiling, src->bo, src->tiling);
  607.  
  608.    for (slice = 0; slice < src_box->depth; slice++) {
  609.       const struct ilo_texture_slice *dst_slice =
  610.          &dst->slice_offsets[dst_level][dst_z + slice];
  611.       const struct ilo_texture_slice *src_slice =
  612.          &src->slice_offsets[src_level][src_box->z + slice];
  613.       unsigned x1, y1, x2, y2, src_x, src_y;
  614.  
  615.       x1 = (dst_slice->x + dst_x) * xscale;
  616.       y1 = dst_slice->y + dst_y;
  617.       x2 = (x1 + src_box->width) * xscale;
  618.       y2 = y1 + src_box->height;
  619.       src_x = (src_slice->x + src_box->x) * xscale;
  620.       src_y = src_slice->y + src_box->y;
  621.  
  622.       /* in blocks */
  623.       x1 /= desc->block.width;
  624.       y1 /= desc->block.height;
  625.       x2 = (x2 + desc->block.width - 1) / desc->block.width;
  626.       y2 = (y2 + desc->block.height - 1) / desc->block.height;
  627.       src_x /= desc->block.width;
  628.       src_y /= desc->block.height;
  629.  
  630.       if (x2 > max_extent || y2 > max_extent ||
  631.           src_x > max_extent || src_y > max_extent ||
  632.           (x2 - x1) * cpp > gen6_max_bytes_per_scanline)
  633.          break;
  634.  
  635.       gen6_emit_XY_SRC_COPY_BLT(ilo->dev,
  636.             dst->bo, dst->tiling, dst->bo_stride, 0,
  637.             x1, y1, x2, y2,
  638.             src->bo, src->tiling, src->bo_stride, 0,
  639.             src_x, src_y, rop, mask, mask,
  640.             ilo->cp);
  641.    }
  642.  
  643.    ilo_blitter_blt_end(blitter, swctrl);
  644.  
  645.    return (slice == src_box->depth);
  646. }
  647.  
  648. bool
  649. ilo_blitter_blt_copy_resource(struct ilo_blitter *blitter,
  650.                               struct pipe_resource *dst, unsigned dst_level,
  651.                               unsigned dst_x, unsigned dst_y, unsigned dst_z,
  652.                               struct pipe_resource *src, unsigned src_level,
  653.                               const struct pipe_box *src_box)
  654. {
  655.    bool success;
  656.  
  657.    if (dst->target == PIPE_BUFFER && src->target == PIPE_BUFFER) {
  658.       const unsigned dst_offset = dst_x;
  659.       const unsigned src_offset = src_box->x;
  660.       const unsigned size = src_box->width;
  661.  
  662.       assert(dst_level == 0 && dst_y == 0 && dst_z == 0);
  663.       assert(src_level == 0 &&
  664.              src_box->y == 0 &&
  665.              src_box->z == 0 &&
  666.              src_box->height == 1 &&
  667.              src_box->depth == 1);
  668.  
  669.       success = buf_copy_region(blitter,
  670.             ilo_buffer(dst), dst_offset, ilo_buffer(src), src_offset, size);
  671.    }
  672.    else if (dst->target != PIPE_BUFFER && src->target != PIPE_BUFFER) {
  673.       success = tex_copy_region(blitter,
  674.             ilo_texture(dst), dst_level, dst_x, dst_y, dst_z,
  675.             ilo_texture(src), src_level, src_box);
  676.    }
  677.    else {
  678.       success = false;
  679.    }
  680.  
  681.    return success;
  682. }
  683.  
  684. bool
  685. ilo_blitter_blt_clear_rt(struct ilo_blitter *blitter,
  686.                          struct pipe_surface *rt,
  687.                          const union pipe_color_union *color,
  688.                          unsigned x, unsigned y,
  689.                          unsigned width, unsigned height)
  690. {
  691.    const int cpp = util_format_get_blocksize(rt->format);
  692.    enum gen6_blt_mask mask;
  693.    union util_color packed;
  694.    bool success;
  695.  
  696.    if (!ilo_3d_pass_render_condition(blitter->ilo))
  697.       return true;
  698.  
  699.    switch (cpp) {
  700.    case 1:
  701.       mask = GEN6_BLT_MASK_8;
  702.       break;
  703.    case 2:
  704.       mask = GEN6_BLT_MASK_16;
  705.       break;
  706.    case 4:
  707.       mask = GEN6_BLT_MASK_32;
  708.       break;
  709.    default:
  710.       return false;
  711.       break;
  712.    }
  713.  
  714.    if (util_format_is_pure_integer(rt->format) ||
  715.        util_format_is_compressed(rt->format))
  716.       return false;
  717.  
  718.    util_pack_color(color->f, rt->format, &packed);
  719.  
  720.    if (rt->texture->target == PIPE_BUFFER) {
  721.       unsigned offset, end, size;
  722.  
  723.       assert(y == 0 && height == 1);
  724.  
  725.       offset = (rt->u.buf.first_element + x) * cpp;
  726.       end = (rt->u.buf.last_element + 1) * cpp;
  727.  
  728.       size = width * cpp;
  729.       if (offset + size > end)
  730.          size = end - offset;
  731.  
  732.       success = buf_clear_region(blitter, ilo_buffer(rt->texture),
  733.             offset, size, packed.ui, mask, mask);
  734.    }
  735.    else {
  736.       struct pipe_box box;
  737.  
  738.       u_box_3d(x, y, rt->u.tex.first_layer, width, height,
  739.             rt->u.tex.last_layer - rt->u.tex.first_layer + 1, &box);
  740.  
  741.       success = tex_clear_region(blitter, ilo_texture(rt->texture),
  742.             rt->u.tex.level, &box, packed.ui, mask, mask);
  743.    }
  744.  
  745.    return success;
  746. }
  747.  
  748. bool
  749. ilo_blitter_blt_clear_zs(struct ilo_blitter *blitter,
  750.                          struct pipe_surface *zs,
  751.                          unsigned clear_flags,
  752.                          double depth, unsigned stencil,
  753.                          unsigned x, unsigned y,
  754.                          unsigned width, unsigned height)
  755. {
  756.    enum gen6_blt_mask value_mask, write_mask;
  757.    struct pipe_box box;
  758.    uint32_t val;
  759.  
  760.    if (!ilo_3d_pass_render_condition(blitter->ilo))
  761.       return true;
  762.  
  763.    switch (zs->format) {
  764.    case PIPE_FORMAT_Z16_UNORM:
  765.       if (!(clear_flags & PIPE_CLEAR_DEPTH))
  766.          return true;
  767.  
  768.       value_mask = GEN6_BLT_MASK_16;
  769.       write_mask = GEN6_BLT_MASK_16;
  770.       break;
  771.    case PIPE_FORMAT_Z32_FLOAT:
  772.       if (!(clear_flags & PIPE_CLEAR_DEPTH))
  773.          return true;
  774.  
  775.       value_mask = GEN6_BLT_MASK_32;
  776.       write_mask = GEN6_BLT_MASK_32;
  777.       break;
  778.    case PIPE_FORMAT_Z24X8_UNORM:
  779.       if (!(clear_flags & PIPE_CLEAR_DEPTH))
  780.          return true;
  781.  
  782.       value_mask = GEN6_BLT_MASK_32;
  783.       write_mask = GEN6_BLT_MASK_32_LO;
  784.       break;
  785.    case PIPE_FORMAT_Z24_UNORM_S8_UINT:
  786.       if (!(clear_flags & PIPE_CLEAR_DEPTHSTENCIL))
  787.          return true;
  788.  
  789.       value_mask = GEN6_BLT_MASK_32;
  790.  
  791.       if ((clear_flags & PIPE_CLEAR_DEPTHSTENCIL) == PIPE_CLEAR_DEPTHSTENCIL)
  792.          write_mask = GEN6_BLT_MASK_32;
  793.       else if (clear_flags & PIPE_CLEAR_DEPTH)
  794.          write_mask = GEN6_BLT_MASK_32_LO;
  795.       else
  796.          write_mask = GEN6_BLT_MASK_32_HI;
  797.       break;
  798.    default:
  799.       return false;
  800.       break;
  801.    }
  802.  
  803.    val = util_pack_z_stencil(zs->format, depth, stencil);
  804.  
  805.    u_box_3d(x, y, zs->u.tex.first_layer, width, height,
  806.          zs->u.tex.last_layer - zs->u.tex.first_layer + 1, &box);
  807.  
  808.    assert(zs->texture->target != PIPE_BUFFER);
  809.  
  810.    return tex_clear_region(blitter, ilo_texture(zs->texture),
  811.          zs->u.tex.level, &box, val, value_mask, write_mask);
  812. }
  813.