Home | History | Annotate | Download | only in ilo
      1 /*
      2  * Mesa 3-D graphics library
      3  *
      4  * Copyright (C) 2012-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 (at) lunarg.com>
     26  */
     27 
     28 #include "util/u_surface.h"
     29 
     30 #include "ilo_blitter.h"
     31 #include "ilo_context.h"
     32 #include "ilo_blit.h"
     33 
     34 static void
     35 ilo_resource_copy_region(struct pipe_context *pipe,
     36                          struct pipe_resource *dst,
     37                          unsigned dst_level,
     38                          unsigned dstx, unsigned dsty, unsigned dstz,
     39                          struct pipe_resource *src,
     40                          unsigned src_level,
     41                          const struct pipe_box *src_box)
     42 {
     43    struct ilo_context *ilo = ilo_context(pipe);
     44 
     45    if (ilo_blitter_blt_copy_resource(ilo->blitter,
     46             dst, dst_level, dstx, dsty, dstz,
     47             src, src_level, src_box))
     48       return;
     49 
     50    if (ilo_blitter_pipe_copy_resource(ilo->blitter,
     51             dst, dst_level, dstx, dsty, dstz,
     52             src, src_level, src_box))
     53       return;
     54 
     55    util_resource_copy_region(&ilo->base, dst, dst_level,
     56          dstx, dsty, dstz, src, src_level, src_box);
     57 }
     58 
     59 static void
     60 ilo_clear(struct pipe_context *pipe,
     61           unsigned buffers,
     62           const union pipe_color_union *color,
     63           double depth,
     64           unsigned stencil)
     65 {
     66    struct ilo_context *ilo = ilo_context(pipe);
     67    struct ilo_state_vector *vec = &ilo->state_vector;
     68 
     69    if ((buffers & PIPE_CLEAR_DEPTHSTENCIL) && vec->fb.state.zsbuf) {
     70       if (ilo_blitter_rectlist_clear_zs(ilo->blitter, vec->fb.state.zsbuf,
     71                buffers & PIPE_CLEAR_DEPTHSTENCIL, depth, stencil))
     72          buffers &= ~PIPE_CLEAR_DEPTHSTENCIL;
     73 
     74       if (!buffers)
     75          return;
     76    }
     77 
     78    ilo_blitter_pipe_clear_fb(ilo->blitter, buffers, color, depth, stencil);
     79 }
     80 
     81 static void
     82 ilo_clear_render_target(struct pipe_context *pipe,
     83                         struct pipe_surface *dst,
     84                         const union pipe_color_union *color,
     85                         unsigned dstx, unsigned dsty,
     86                         unsigned width, unsigned height,
     87                         bool render_condition_enabled)
     88 {
     89    struct ilo_context *ilo = ilo_context(pipe);
     90 
     91    if (!width || !height || dstx >= dst->width || dsty >= dst->height)
     92       return;
     93 
     94    if (dstx + width > dst->width)
     95       width = dst->width - dstx;
     96    if (dsty + height > dst->height)
     97       height = dst->height - dsty;
     98 
     99    if (ilo_blitter_blt_clear_rt(ilo->blitter,
    100             dst, color, dstx, dsty, width, height))
    101       return;
    102 
    103    ilo_blitter_pipe_clear_rt(ilo->blitter,
    104          dst, color, dstx, dsty, width, height);
    105 }
    106 
    107 static void
    108 ilo_clear_depth_stencil(struct pipe_context *pipe,
    109                         struct pipe_surface *dst,
    110                         unsigned clear_flags,
    111                         double depth,
    112                         unsigned stencil,
    113                         unsigned dstx, unsigned dsty,
    114                         unsigned width, unsigned height,
    115                         bool render_condition_enabled)
    116 {
    117    struct ilo_context *ilo = ilo_context(pipe);
    118 
    119    if (!width || !height || dstx >= dst->width || dsty >= dst->height)
    120       return;
    121 
    122    if (dstx + width > dst->width)
    123       width = dst->width - dstx;
    124    if (dsty + height > dst->height)
    125       height = dst->height - dsty;
    126 
    127    if (ilo_blitter_blt_clear_zs(ilo->blitter,
    128             dst, clear_flags, depth, stencil, dstx, dsty, width, height))
    129       return;
    130 
    131    ilo_blitter_pipe_clear_zs(ilo->blitter,
    132          dst, clear_flags, depth, stencil, dstx, dsty, width, height);
    133 }
    134 
    135 static void
    136 ilo_blit(struct pipe_context *pipe, const struct pipe_blit_info *info)
    137 {
    138    struct ilo_context *ilo = ilo_context(pipe);
    139 
    140    ilo_blitter_pipe_blit(ilo->blitter, info);
    141 }
    142 
    143 static void
    144 ilo_flush_resource(struct pipe_context *pipe, struct pipe_resource *res)
    145 {
    146    struct ilo_context *ilo = ilo_context(pipe);
    147    const unsigned flags = ILO_TEXTURE_CPU_READ |
    148                           ILO_TEXTURE_BLT_READ |
    149                           ILO_TEXTURE_RENDER_READ;
    150 
    151    ilo_blit_resolve_resource(ilo, res, flags);
    152 }
    153 
    154 void
    155 ilo_blit_resolve_slices_for_hiz(struct ilo_context *ilo,
    156                                 struct pipe_resource *res, unsigned level,
    157                                 unsigned first_slice, unsigned num_slices,
    158                                 unsigned resolve_flags)
    159 {
    160    struct ilo_texture *tex = ilo_texture(res);
    161    const unsigned any_reader =
    162       ILO_TEXTURE_RENDER_READ |
    163       ILO_TEXTURE_BLT_READ |
    164       ILO_TEXTURE_CPU_READ;
    165    const unsigned other_writers =
    166       ILO_TEXTURE_BLT_WRITE |
    167       ILO_TEXTURE_CPU_WRITE;
    168    unsigned i;
    169 
    170    assert(tex->base.target != PIPE_BUFFER &&
    171           ilo_image_can_enable_aux(&tex->image, level));
    172 
    173    if (resolve_flags & ILO_TEXTURE_RENDER_WRITE) {
    174       /*
    175        * When ILO_TEXTURE_RENDER_WRITE is set, there can be no reader.  We
    176        * need to perform a HiZ Buffer Resolve in case the resource was
    177        * previously written by another writer, unless this is a clear.
    178        *
    179        * When slices have different clear values, we perform a Depth Buffer
    180        * Resolve on all slices not sharing the clear value of the first slice.
    181        * After resolving, those slices do not use 3DSTATE_CLEAR_PARAMS and can
    182        * be made to have the same clear value as the first slice does.  This
    183        * way,
    184        *
    185        *  - 3DSTATE_CLEAR_PARAMS can be set to the clear value of any slice
    186        *  - we will not resolve unnecessarily next time this function is
    187        *    called
    188        *
    189        * Since slice clear value is the value the slice is cleared to when
    190        * ILO_TEXTURE_CLEAR is set, the bit needs to be unset.
    191        */
    192       assert(!(resolve_flags & (other_writers | any_reader)));
    193 
    194       if (!(resolve_flags & ILO_TEXTURE_CLEAR)) {
    195          const uint32_t first_clear_value = ilo_texture_get_slice(tex,
    196                level, first_slice)->clear_value;
    197          bool set_clear_value = false;
    198 
    199          for (i = 0; i < num_slices; i++) {
    200             const struct ilo_texture_slice *slice =
    201                ilo_texture_get_slice(tex, level, first_slice + i);
    202 
    203             if (slice->flags & other_writers) {
    204                ilo_blitter_rectlist_resolve_hiz(ilo->blitter,
    205                      res, level, first_slice + i);
    206             } else if (slice->clear_value != first_clear_value &&
    207                        (slice->flags & ILO_TEXTURE_RENDER_WRITE)) {
    208                ilo_blitter_rectlist_resolve_z(ilo->blitter,
    209                      res, level, first_slice + i);
    210                set_clear_value = true;
    211             }
    212          }
    213 
    214          if (set_clear_value) {
    215             /* ILO_TEXTURE_CLEAR will be cleared later */
    216             ilo_texture_set_slice_clear_value(tex, level,
    217                   first_slice, num_slices, first_clear_value);
    218          }
    219       }
    220    }
    221    else if ((resolve_flags & any_reader) ||
    222             ((resolve_flags & other_writers) &&
    223              !(resolve_flags & ILO_TEXTURE_CLEAR))) {
    224       /*
    225        * When there is at least a reader or writer, we need to perform a
    226        * Depth Buffer Resolve in case the resource was previously written
    227        * by ILO_TEXTURE_RENDER_WRITE.
    228        */
    229       for (i = 0; i < num_slices; i++) {
    230          const struct ilo_texture_slice *slice =
    231             ilo_texture_get_slice(tex, level, first_slice + i);
    232 
    233          if (slice->flags & ILO_TEXTURE_RENDER_WRITE) {
    234             ilo_blitter_rectlist_resolve_z(ilo->blitter,
    235                   &tex->base, level, first_slice + i);
    236          }
    237       }
    238    }
    239 }
    240 
    241 /**
    242  * Initialize blit-related functions.
    243  */
    244 void
    245 ilo_init_blit_functions(struct ilo_context *ilo)
    246 {
    247    ilo->base.resource_copy_region = ilo_resource_copy_region;
    248    ilo->base.blit = ilo_blit;
    249    ilo->base.flush_resource = ilo_flush_resource;
    250 
    251    ilo->base.clear = ilo_clear;
    252    ilo->base.clear_render_target = ilo_clear_render_target;
    253    ilo->base.clear_depth_stencil = ilo_clear_depth_stencil;
    254 }
    255