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@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
34static void
35ilo_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
59static void
60ilo_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
81static void
82ilo_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
107static void
108ilo_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
135static void
136ilo_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
143static void
144ilo_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
154void
155ilo_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 */
244void
245ilo_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