1/*
2 * Copyright © 2017 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included
12 * in all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 * DEALINGS IN THE SOFTWARE.
21 */
22
23#include <stdio.h>
24#include <errno.h>
25#include "pipe/p_defines.h"
26#include "pipe/p_state.h"
27#include "pipe/p_context.h"
28#include "pipe/p_screen.h"
29#include "util/u_inlines.h"
30#include "util/u_surface.h"
31#include "util/format/u_format.h"
32#include "util/u_upload_mgr.h"
33#include "util/ralloc.h"
34#include "crocus_context.h"
35#include "crocus_resource.h"
36#include "crocus_screen.h"
37#include "intel/compiler/brw_compiler.h"
38#include "util/format_srgb.h"
39
40static bool
41crocus_is_color_fast_clear_compatible(struct crocus_context *ice,
42                                      enum isl_format format,
43                                      const union isl_color_value color)
44{
45   if (isl_format_has_int_channel(format)) {
46      perf_debug(&ice->dbg, "Integer fast clear not enabled for %s",
47                 isl_format_get_name(format));
48      return false;
49   }
50
51   for (int i = 0; i < 4; i++) {
52      if (!isl_format_has_color_component(format, i)) {
53         continue;
54      }
55
56      if (color.f32[i] != 0.0f && color.f32[i] != 1.0f) {
57         return false;
58      }
59   }
60
61   return true;
62}
63
64static bool
65can_fast_clear_color(struct crocus_context *ice,
66                     struct pipe_resource *p_res,
67                     unsigned level,
68                     const struct pipe_box *box,
69                     bool render_condition_enabled,
70                     enum isl_format format,
71                     enum isl_format render_format,
72                     union isl_color_value color)
73{
74   struct crocus_resource *res = (void *) p_res;
75
76   if (INTEL_DEBUG(DEBUG_NO_FAST_CLEAR))
77      return false;
78
79   if (!isl_aux_usage_has_fast_clears(res->aux.usage))
80      return false;
81
82   /* Check for partial clear */
83   if (box->x > 0 || box->y > 0 ||
84       box->width < u_minify(p_res->width0, level) ||
85       box->height < u_minify(p_res->height0, level)) {
86      return false;
87   }
88
89   /* Avoid conditional fast clears to maintain correct tracking of the aux
90    * state (see iris_resource_finish_write for more info). Note that partial
91    * fast clears (if they existed) would not pose a problem with conditional
92    * rendering.
93    */
94   if (render_condition_enabled &&
95       ice->state.predicate == CROCUS_PREDICATE_STATE_USE_BIT) {
96      return false;
97   }
98
99   /* We store clear colors as floats or uints as needed.  If there are
100    * texture views in play, the formats will not properly be respected
101    * during resolves because the resolve operations only know about the
102    * resource and not the renderbuffer.
103    */
104   if (isl_format_srgb_to_linear(render_format) !=
105       isl_format_srgb_to_linear(format)) {
106      return false;
107   }
108
109   /* XXX: if (irb->mt->supports_fast_clear)
110    * see intel_miptree_create_for_dri_image()
111    */
112
113   if (!crocus_is_color_fast_clear_compatible(ice, format, color))
114      return false;
115
116   return true;
117}
118
119static union isl_color_value
120convert_fast_clear_color(struct crocus_context *ice,
121                         struct crocus_resource *res,
122                         enum isl_format render_format,
123                         const union isl_color_value color)
124{
125   union isl_color_value override_color = color;
126   struct pipe_resource *p_res = (void *) res;
127
128   const enum pipe_format format = p_res->format;
129   const struct util_format_description *desc =
130      util_format_description(format);
131   unsigned colormask = util_format_colormask(desc);
132
133   if (util_format_is_intensity(format) ||
134       util_format_is_luminance(format) ||
135       util_format_is_luminance_alpha(format)) {
136      override_color.u32[1] = override_color.u32[0];
137      override_color.u32[2] = override_color.u32[0];
138      if (util_format_is_intensity(format))
139         override_color.u32[3] = override_color.u32[0];
140   } else {
141      for (int chan = 0; chan < 3; chan++) {
142         if (!(colormask & (1 << chan)))
143            override_color.u32[chan] = 0;
144      }
145   }
146
147   if (util_format_is_unorm(format)) {
148      for (int i = 0; i < 4; i++)
149         override_color.f32[i] = CLAMP(override_color.f32[i], 0.0f, 1.0f);
150   } else if (util_format_is_snorm(format)) {
151      for (int i = 0; i < 4; i++)
152         override_color.f32[i] = CLAMP(override_color.f32[i], -1.0f, 1.0f);
153   } else if (util_format_is_pure_uint(format)) {
154      for (int i = 0; i < 4; i++) {
155         unsigned bits = util_format_get_component_bits(
156            format, UTIL_FORMAT_COLORSPACE_RGB, i);
157         if (bits < 32) {
158            uint32_t max = (1u << bits) - 1;
159            override_color.u32[i] = MIN2(override_color.u32[i], max);
160         }
161      }
162   } else if (util_format_is_pure_sint(format)) {
163      for (int i = 0; i < 4; i++) {
164         unsigned bits = util_format_get_component_bits(
165            format, UTIL_FORMAT_COLORSPACE_RGB, i);
166         if (bits < 32) {
167            int32_t max = (1 << (bits - 1)) - 1;
168            int32_t min = -(1 << (bits - 1));
169            override_color.i32[i] = CLAMP(override_color.i32[i], min, max);
170         }
171      }
172   } else if (format == PIPE_FORMAT_R11G11B10_FLOAT ||
173              format == PIPE_FORMAT_R9G9B9E5_FLOAT) {
174      /* these packed float formats only store unsigned values */
175      for (int i = 0; i < 4; i++)
176         override_color.f32[i] = MAX2(override_color.f32[i], 0.0f);
177   }
178
179   if (!(colormask & 1 << 3)) {
180      if (util_format_is_pure_integer(format))
181         override_color.u32[3] = 1;
182      else
183         override_color.f32[3] = 1.0f;
184   }
185
186   /* Handle linear to SRGB conversion */
187   if (isl_format_is_srgb(render_format)) {
188      for (int i = 0; i < 3; i++) {
189         override_color.f32[i] =
190            util_format_linear_to_srgb_float(override_color.f32[i]);
191      }
192   }
193
194   return override_color;
195}
196
197static void
198fast_clear_color(struct crocus_context *ice,
199                 struct crocus_resource *res,
200                 unsigned level,
201                 const struct pipe_box *box,
202                 enum isl_format format,
203                 union isl_color_value color,
204                 enum blorp_batch_flags blorp_flags)
205{
206   struct crocus_batch *batch = &ice->batches[CROCUS_BATCH_RENDER];
207   struct crocus_screen *screen = batch->screen;
208   struct pipe_resource *p_res = (void *) res;
209
210   color = convert_fast_clear_color(ice, res, format, color);
211
212   bool color_changed = !!memcmp(&res->aux.clear_color, &color,
213                                 sizeof(color));
214
215   if (color_changed) {
216      /* If we are clearing to a new clear value, we need to resolve fast
217       * clears from other levels/layers first, since we can't have different
218       * levels/layers with different fast clear colors.
219       */
220      for (unsigned res_lvl = 0; res_lvl < res->surf.levels; res_lvl++) {
221         const unsigned level_layers =
222            crocus_get_num_logical_layers(res, res_lvl);
223         for (unsigned layer = 0; layer < level_layers; layer++) {
224            if (res_lvl == level &&
225                layer >= box->z &&
226                layer < box->z + box->depth) {
227               /* We're going to clear this layer anyway.  Leave it alone. */
228               continue;
229            }
230
231            enum isl_aux_state aux_state =
232               crocus_resource_get_aux_state(res, res_lvl, layer);
233
234            if (aux_state != ISL_AUX_STATE_CLEAR &&
235                aux_state != ISL_AUX_STATE_PARTIAL_CLEAR &&
236                aux_state != ISL_AUX_STATE_COMPRESSED_CLEAR) {
237               /* This slice doesn't have any fast-cleared bits. */
238               continue;
239            }
240
241            /* If we got here, then the level may have fast-clear bits that use
242             * the old clear value.  We need to do a color resolve to get rid
243             * of their use of the clear color before we can change it.
244             * Fortunately, few applications ever change their clear color at
245             * different levels/layers, so this shouldn't happen often.
246             */
247            crocus_resource_prepare_access(ice, res,
248                                           res_lvl, 1, layer, 1,
249                                           res->aux.usage,
250                                           false);
251            perf_debug(&ice->dbg,
252                       "Resolving resource (%p) level %d, layer %d: color changing from "
253                       "(%0.2f, %0.2f, %0.2f, %0.2f) to "
254                       "(%0.2f, %0.2f, %0.2f, %0.2f)\n",
255                       res, res_lvl, layer,
256                       res->aux.clear_color.f32[0],
257                       res->aux.clear_color.f32[1],
258                       res->aux.clear_color.f32[2],
259                       res->aux.clear_color.f32[3],
260                       color.f32[0], color.f32[1], color.f32[2], color.f32[3]);
261         }
262      }
263   }
264
265   crocus_resource_set_clear_color(ice, res, color);
266
267   /* If the buffer is already in ISL_AUX_STATE_CLEAR, and the color hasn't
268    * changed, the clear is redundant and can be skipped.
269    */
270   const enum isl_aux_state aux_state =
271      crocus_resource_get_aux_state(res, level, box->z);
272   if (!color_changed && box->depth == 1 && aux_state == ISL_AUX_STATE_CLEAR)
273      return;
274
275   /* Ivybrigde PRM Vol 2, Part 1, "11.7 MCS Buffer for Render Target(s)":
276    *
277    *    "Any transition from any value in {Clear, Render, Resolve} to a
278    *    different value in {Clear, Render, Resolve} requires end of pipe
279    *    synchronization."
280    *
281    * In other words, fast clear ops are not properly synchronized with
282    * other drawing.  We need to use a PIPE_CONTROL to ensure that the
283    * contents of the previous draw hit the render target before we resolve
284    * and again afterwards to ensure that the resolve is complete before we
285    * do any more regular drawing.
286    */
287   crocus_emit_end_of_pipe_sync(batch,
288                                "fast clear: pre-flush",
289                                PIPE_CONTROL_RENDER_TARGET_FLUSH);
290
291   /* If we reach this point, we need to fast clear to change the state to
292    * ISL_AUX_STATE_CLEAR, or to update the fast clear color (or both).
293    */
294   blorp_flags |= color_changed ? 0 : BLORP_BATCH_NO_UPDATE_CLEAR_COLOR;
295
296   struct blorp_batch blorp_batch;
297   blorp_batch_init(&ice->blorp, &blorp_batch, batch, blorp_flags);
298
299   struct blorp_surf surf;
300   crocus_blorp_surf_for_resource(&screen->vtbl, &batch->screen->isl_dev, &surf,
301                                  p_res, res->aux.usage, level, true);
302
303   /* In newer gens (> 9), the hardware will do a linear -> sRGB conversion of
304    * the clear color during the fast clear, if the surface format is of sRGB
305    * type. We use the linear version of the surface format here to prevent
306    * that from happening, since we already do our own linear -> sRGB
307    * conversion in convert_fast_clear_color().
308    */
309   blorp_fast_clear(&blorp_batch, &surf, isl_format_srgb_to_linear(format),
310                    ISL_SWIZZLE_IDENTITY,
311                    level, box->z, box->depth,
312                    box->x, box->y, box->x + box->width,
313                    box->y + box->height);
314   blorp_batch_finish(&blorp_batch);
315   crocus_emit_end_of_pipe_sync(batch,
316                                "fast clear: post flush",
317                                PIPE_CONTROL_RENDER_TARGET_FLUSH);
318
319   crocus_resource_set_aux_state(ice, res, level, box->z,
320                                 box->depth, ISL_AUX_STATE_CLEAR);
321   ice->state.stage_dirty |= CROCUS_ALL_STAGE_DIRTY_BINDINGS;
322   return;
323}
324
325static void
326clear_color(struct crocus_context *ice,
327            struct pipe_resource *p_res,
328            unsigned level,
329            const struct pipe_box *box,
330            bool render_condition_enabled,
331            enum isl_format format,
332            struct isl_swizzle swizzle,
333            union isl_color_value color)
334{
335   struct crocus_resource *res = (void *) p_res;
336   struct crocus_batch *batch = &ice->batches[CROCUS_BATCH_RENDER];
337   struct crocus_screen *screen = batch->screen;
338   const struct intel_device_info *devinfo = &batch->screen->devinfo;
339   enum blorp_batch_flags blorp_flags = 0;
340
341   if (render_condition_enabled) {
342      if (!crocus_check_conditional_render(ice))
343         return;
344
345      if (ice->state.predicate == CROCUS_PREDICATE_STATE_USE_BIT)
346         blorp_flags |= BLORP_BATCH_PREDICATE_ENABLE;
347   }
348
349   if (p_res->target == PIPE_BUFFER)
350      util_range_add(&res->base.b, &res->valid_buffer_range, box->x, box->x + box->width);
351
352   crocus_batch_maybe_flush(batch, 1500);
353
354   bool can_fast_clear = can_fast_clear_color(ice, p_res, level, box,
355                                              render_condition_enabled,
356                                              res->surf.format, format, color);
357   if (can_fast_clear) {
358      fast_clear_color(ice, res, level, box, format, color,
359                       blorp_flags);
360      return;
361   }
362
363   enum isl_aux_usage aux_usage =
364      crocus_resource_render_aux_usage(ice, res, level, format, false);
365
366   crocus_resource_prepare_render(ice, res, level,
367                                  box->z, box->depth, aux_usage);
368
369   struct blorp_surf surf;
370   crocus_blorp_surf_for_resource(&screen->vtbl, &batch->screen->isl_dev, &surf,
371                                  p_res, aux_usage, level, true);
372
373   struct blorp_batch blorp_batch;
374   blorp_batch_init(&ice->blorp, &blorp_batch, batch, blorp_flags);
375
376   if (!isl_format_supports_rendering(devinfo, format) &&
377       isl_format_is_rgbx(format))
378      format = isl_format_rgbx_to_rgba(format);
379
380   blorp_clear(&blorp_batch, &surf, format, swizzle,
381               level, box->z, box->depth, box->x, box->y,
382               box->x + box->width, box->y + box->height,
383               color, 0 /* color_write_disable */);
384
385   blorp_batch_finish(&blorp_batch);
386   crocus_flush_and_dirty_for_history(ice, batch, res,
387                                      PIPE_CONTROL_RENDER_TARGET_FLUSH,
388                                      "cache history: post color clear");
389
390   crocus_resource_finish_render(ice, res, level,
391                                 box->z, box->depth, aux_usage);
392}
393
394static bool
395can_fast_clear_depth(struct crocus_context *ice,
396                     struct crocus_resource *res,
397                     unsigned level,
398                     const struct pipe_box *box,
399                     bool render_condition_enabled,
400                     float depth)
401{
402   struct pipe_resource *p_res = (void *) res;
403   struct pipe_context *ctx = (void *) ice;
404   struct crocus_screen *screen = (void *) ctx->screen;
405   const struct intel_device_info *devinfo = &screen->devinfo;
406
407   if (devinfo->ver < 6)
408      return false;
409
410   if (INTEL_DEBUG(DEBUG_NO_FAST_CLEAR))
411      return false;
412
413   /* Check for partial clears */
414   if (box->x > 0 || box->y > 0 ||
415       box->width < u_minify(p_res->width0, level) ||
416       box->height < u_minify(p_res->height0, level)) {
417      return false;
418   }
419
420   /* Avoid conditional fast clears to maintain correct tracking of the aux
421    * state (see iris_resource_finish_write for more info). Note that partial
422    * fast clears would not pose a problem with conditional rendering.
423    */
424   if (render_condition_enabled &&
425       ice->state.predicate == CROCUS_PREDICATE_STATE_USE_BIT) {
426      return false;
427   }
428
429   if (!crocus_resource_level_has_hiz(res, level))
430      return false;
431
432   if (res->base.b.format == PIPE_FORMAT_Z16_UNORM) {
433      /* From the Sandy Bridge PRM, volume 2 part 1, page 314:
434       *
435       *     "[DevSNB+]: Several cases exist where Depth Buffer Clear cannot be
436       *      enabled (the legacy method of clearing must be performed):
437       *
438       *      - DevSNB{W/A}]: When depth buffer format is D16_UNORM and the
439       *        width of the map (LOD0) is not multiple of 16, fast clear
440       *        optimization must be disabled.
441       */
442      if (devinfo->ver == 6 &&
443          (u_minify(res->surf.phys_level0_sa.width,
444                    level) % 16) != 0)
445         return false;
446   }
447   return true;
448}
449
450static void
451fast_clear_depth(struct crocus_context *ice,
452                 struct crocus_resource *res,
453                 unsigned level,
454                 const struct pipe_box *box,
455                 float depth)
456{
457   struct pipe_resource *p_res = (void *) res;
458   struct crocus_batch *batch = &ice->batches[CROCUS_BATCH_RENDER];
459
460   /* Quantize the clear value to what can be stored in the actual depth
461    * buffer.  This makes the following check more accurate because it now
462    * checks if the actual depth bits will match.  It also prevents us from
463    * getting a too-accurate depth value during depth testing or when sampling
464    * with HiZ enabled.
465    */
466   const unsigned nbits = p_res->format == PIPE_FORMAT_Z16_UNORM ? 16 : 24;
467   const uint32_t depth_max = (1 << nbits) - 1;
468   depth = p_res->format == PIPE_FORMAT_Z32_FLOAT ? depth :
469      (unsigned)(depth * depth_max) / (float)depth_max;
470
471   bool update_clear_depth = false;
472
473   /* If we're clearing to a new clear value, then we need to resolve any clear
474    * flags out of the HiZ buffer into the real depth buffer.
475    */
476   if (res->aux.clear_color.f32[0] != depth) {
477      for (unsigned res_level = 0; res_level < res->surf.levels; res_level++) {
478         if (!crocus_resource_level_has_hiz(res, res_level))
479            continue;
480
481         const unsigned level_layers =
482            crocus_get_num_logical_layers(res, res_level);
483         for (unsigned layer = 0; layer < level_layers; layer++) {
484            if (res_level == level &&
485                layer >= box->z &&
486                layer < box->z + box->depth) {
487               /* We're going to clear this layer anyway.  Leave it alone. */
488               continue;
489            }
490
491            enum isl_aux_state aux_state =
492               crocus_resource_get_aux_state(res, res_level, layer);
493
494            if (aux_state != ISL_AUX_STATE_CLEAR &&
495                aux_state != ISL_AUX_STATE_COMPRESSED_CLEAR) {
496               /* This slice doesn't have any fast-cleared bits. */
497               continue;
498            }
499
500            /* If we got here, then the level may have fast-clear bits that
501             * use the old clear value.  We need to do a depth resolve to get
502             * rid of their use of the clear value before we can change it.
503             * Fortunately, few applications ever change their depth clear
504             * value so this shouldn't happen often.
505             */
506            crocus_hiz_exec(ice, batch, res, res_level, layer, 1,
507                            ISL_AUX_OP_FULL_RESOLVE, false);
508            crocus_resource_set_aux_state(ice, res, res_level, layer, 1,
509                                          ISL_AUX_STATE_RESOLVED);
510         }
511      }
512      const union isl_color_value clear_value = { .f32 = {depth, } };
513      crocus_resource_set_clear_color(ice, res, clear_value);
514      update_clear_depth = true;
515   }
516
517   for (unsigned l = 0; l < box->depth; l++) {
518      enum isl_aux_state aux_state =
519         crocus_resource_level_has_hiz(res, level) ?
520         crocus_resource_get_aux_state(res, level, box->z + l) :
521         ISL_AUX_STATE_AUX_INVALID;
522      if (update_clear_depth || aux_state != ISL_AUX_STATE_CLEAR) {
523         if (aux_state == ISL_AUX_STATE_CLEAR) {
524            perf_debug(&ice->dbg, "Performing HiZ clear just to update the "
525                       "depth clear value\n");
526         }
527         crocus_hiz_exec(ice, batch, res, level,
528                         box->z + l, 1, ISL_AUX_OP_FAST_CLEAR,
529                         update_clear_depth);
530      }
531   }
532
533   crocus_resource_set_aux_state(ice, res, level, box->z, box->depth,
534                                 ISL_AUX_STATE_CLEAR);
535   ice->state.dirty |= CROCUS_DIRTY_DEPTH_BUFFER;
536}
537
538static void
539clear_depth_stencil(struct crocus_context *ice,
540                    struct pipe_resource *p_res,
541                    unsigned level,
542                    const struct pipe_box *box,
543                    bool render_condition_enabled,
544                    bool clear_depth,
545                    bool clear_stencil,
546                    float depth,
547                    uint8_t stencil)
548{
549   struct crocus_resource *res = (void *) p_res;
550   struct crocus_batch *batch = &ice->batches[CROCUS_BATCH_RENDER];
551   struct crocus_screen *screen = batch->screen;
552   enum blorp_batch_flags blorp_flags = 0;
553
554   if (render_condition_enabled) {
555      if (!crocus_check_conditional_render(ice))
556         return;
557
558      if (ice->state.predicate == CROCUS_PREDICATE_STATE_USE_BIT)
559         blorp_flags |= BLORP_BATCH_PREDICATE_ENABLE;
560   }
561
562   crocus_batch_maybe_flush(batch, 1500);
563
564   struct crocus_resource *z_res;
565   struct crocus_resource *stencil_res;
566   struct blorp_surf z_surf;
567   struct blorp_surf stencil_surf;
568
569   crocus_get_depth_stencil_resources(&batch->screen->devinfo, p_res, &z_res, &stencil_res);
570   if (z_res && clear_depth &&
571       can_fast_clear_depth(ice, z_res, level, box, render_condition_enabled,
572                            depth)) {
573      fast_clear_depth(ice, z_res, level, box, depth);
574      crocus_flush_and_dirty_for_history(ice, batch, res, 0,
575                                         "cache history: post fast Z clear");
576      clear_depth = false;
577      z_res = NULL;
578   }
579
580   /* At this point, we might have fast cleared the depth buffer. So if there's
581    * no stencil clear pending, return early.
582    */
583   if (!(clear_depth || (clear_stencil && stencil_res))) {
584      return;
585   }
586
587   if (clear_depth && z_res) {
588      const enum isl_aux_usage aux_usage =
589         crocus_resource_render_aux_usage(ice, z_res, level, z_res->surf.format,
590                                          false);
591      crocus_resource_prepare_render(ice, z_res, level, box->z, box->depth,
592                                     aux_usage);
593      crocus_blorp_surf_for_resource(&screen->vtbl, &batch->screen->isl_dev,
594                                     &z_surf, &z_res->base.b, aux_usage,
595                                     level, true);
596   }
597
598   struct blorp_batch blorp_batch;
599   blorp_batch_init(&ice->blorp, &blorp_batch, batch, blorp_flags);
600
601   uint8_t stencil_mask = clear_stencil && stencil_res ? 0xff : 0;
602   if (stencil_mask) {
603      crocus_resource_prepare_access(ice, stencil_res, level, 1, box->z,
604                                     box->depth, stencil_res->aux.usage, false);
605      crocus_blorp_surf_for_resource(&screen->vtbl, &batch->screen->isl_dev,
606                                     &stencil_surf, &stencil_res->base.b,
607                                     stencil_res->aux.usage, level, true);
608   }
609
610   blorp_clear_depth_stencil(&blorp_batch, &z_surf, &stencil_surf,
611                             level, box->z, box->depth,
612                             box->x, box->y,
613                             box->x + box->width,
614                             box->y + box->height,
615                             clear_depth && z_res, depth,
616                             stencil_mask, stencil);
617
618   blorp_batch_finish(&blorp_batch);
619   crocus_flush_and_dirty_for_history(ice, batch, res, 0,
620                                      "cache history: post slow ZS clear");
621
622   if (clear_depth && z_res) {
623      crocus_resource_finish_render(ice, z_res, level,
624                                    box->z, box->depth, z_surf.aux_usage);
625   }
626
627   if (stencil_mask) {
628      crocus_resource_finish_write(ice, stencil_res, level, box->z, box->depth,
629                                   stencil_res->aux.usage);
630   }
631}
632
633/**
634 * The pipe->clear() driver hook.
635 *
636 * This clears buffers attached to the current draw framebuffer.
637 */
638static void
639crocus_clear(struct pipe_context *ctx,
640             unsigned buffers,
641             const struct pipe_scissor_state *scissor_state,
642             const union pipe_color_union *p_color,
643             double depth,
644             unsigned stencil)
645{
646   struct crocus_context *ice = (void *) ctx;
647   struct pipe_framebuffer_state *cso_fb = &ice->state.framebuffer;
648   struct crocus_screen *screen = (void *) ctx->screen;
649   const struct intel_device_info *devinfo = &screen->devinfo;
650   assert(buffers != 0);
651
652   struct pipe_box box = {
653      .width = cso_fb->width,
654      .height = cso_fb->height,
655   };
656
657   if (scissor_state) {
658      box.x = scissor_state->minx;
659      box.y = scissor_state->miny;
660      box.width = MIN2(box.width, scissor_state->maxx - scissor_state->minx);
661      box.height = MIN2(box.height, scissor_state->maxy - scissor_state->miny);
662   }
663
664   if (buffers & PIPE_CLEAR_DEPTHSTENCIL) {
665      if (devinfo->ver < 6) {
666         crocus_blitter_begin(ice, CROCUS_SAVE_FRAGMENT_STATE, true);
667         util_blitter_clear(ice->blitter, cso_fb->width, cso_fb->height,
668                            util_framebuffer_get_num_layers(cso_fb),
669                            buffers & PIPE_CLEAR_DEPTHSTENCIL, p_color, depth, stencil, false);
670      } else {
671         struct pipe_surface *psurf = cso_fb->zsbuf;
672         box.depth = psurf->u.tex.last_layer - psurf->u.tex.first_layer + 1;
673         box.z = psurf->u.tex.first_layer;
674
675         clear_depth_stencil(ice, psurf->texture, psurf->u.tex.level, &box, true,
676                             buffers & PIPE_CLEAR_DEPTH,
677                             buffers & PIPE_CLEAR_STENCIL,
678                             depth, stencil);
679      }
680      buffers &= ~PIPE_CLEAR_DEPTHSTENCIL;
681   }
682
683   if (buffers & PIPE_CLEAR_COLOR) {
684      /* pipe_color_union and isl_color_value are interchangeable */
685      union isl_color_value *color = (void *) p_color;
686
687      for (unsigned i = 0; i < cso_fb->nr_cbufs; i++) {
688         if (buffers & (PIPE_CLEAR_COLOR0 << i)) {
689            struct pipe_surface *psurf = cso_fb->cbufs[i];
690            struct crocus_surface *isurf = (void *) psurf;
691            box.depth = psurf->u.tex.last_layer - psurf->u.tex.first_layer + 1,
692            box.z = psurf->u.tex.first_layer,
693
694            clear_color(ice, psurf->texture, psurf->u.tex.level, &box,
695                        true, isurf->view.format, isurf->view.swizzle,
696                        *color);
697         }
698      }
699   }
700}
701
702/**
703 * The pipe->clear_texture() driver hook.
704 *
705 * This clears the given texture resource.
706 */
707static void
708crocus_clear_texture(struct pipe_context *ctx,
709                     struct pipe_resource *p_res,
710                     unsigned level,
711                     const struct pipe_box *box,
712                     const void *data)
713{
714   struct crocus_context *ice = (void *) ctx;
715   struct crocus_screen *screen = (void *) ctx->screen;
716   const struct intel_device_info *devinfo = &screen->devinfo;
717   struct crocus_resource *res = (void *) p_res;
718
719   if (devinfo->ver < 6) {
720      util_clear_texture(ctx, p_res,
721                         level, box, data);
722      return;
723   }
724
725   if (crocus_resource_unfinished_aux_import(res))
726      crocus_resource_finish_aux_import(ctx->screen, res);
727
728   if (util_format_is_depth_or_stencil(p_res->format)) {
729      const struct util_format_unpack_description *fmt_unpack =
730         util_format_unpack_description(p_res->format);
731
732      float depth = 0.0;
733      uint8_t stencil = 0;
734
735      if (fmt_unpack->unpack_z_float)
736         fmt_unpack->unpack_z_float(&depth, 0, data, 0, 1, 1);
737
738      if (fmt_unpack->unpack_s_8uint)
739         fmt_unpack->unpack_s_8uint(&stencil, 0, data, 0, 1, 1);
740
741      clear_depth_stencil(ice, p_res, level, box, true, true, true,
742                          depth, stencil);
743   } else {
744      union isl_color_value color;
745      struct crocus_resource *res = (void *) p_res;
746      enum isl_format format = res->surf.format;
747
748      if (!isl_format_supports_rendering(devinfo, format)) {
749         const struct isl_format_layout *fmtl = isl_format_get_layout(format);
750         // XXX: actually just get_copy_format_for_bpb from BLORP
751         // XXX: don't cut and paste this
752         switch (fmtl->bpb) {
753         case 8:   format = ISL_FORMAT_R8_UINT;           break;
754         case 16:  format = ISL_FORMAT_R8G8_UINT;         break;
755         case 24:  format = ISL_FORMAT_R8G8B8_UINT;       break;
756         case 32:  format = ISL_FORMAT_R8G8B8A8_UINT;     break;
757         case 48:  format = ISL_FORMAT_R16G16B16_UINT;    break;
758         case 64:  format = ISL_FORMAT_R16G16B16A16_UINT; break;
759         case 96:  format = ISL_FORMAT_R32G32B32_UINT;    break;
760         case 128: format = ISL_FORMAT_R32G32B32A32_UINT; break;
761         default:
762            unreachable("Unknown format bpb");
763         }
764
765         /* No aux surfaces for non-renderable surfaces */
766         assert(res->aux.usage == ISL_AUX_USAGE_NONE);
767      }
768
769      isl_color_value_unpack(&color, format, data);
770
771      clear_color(ice, p_res, level, box, true, format,
772                  ISL_SWIZZLE_IDENTITY, color);
773   }
774}
775
776/**
777 * The pipe->clear_render_target() driver hook.
778 *
779 * This clears the given render target surface.
780 */
781static void
782crocus_clear_render_target(struct pipe_context *ctx,
783                           struct pipe_surface *psurf,
784                           const union pipe_color_union *p_color,
785                           unsigned dst_x, unsigned dst_y,
786                           unsigned width, unsigned height,
787                           bool render_condition_enabled)
788{
789   struct crocus_context *ice = (void *) ctx;
790   struct crocus_surface *isurf = (void *) psurf;
791   struct pipe_box box = {
792      .x = dst_x,
793      .y = dst_y,
794      .z = psurf->u.tex.first_layer,
795      .width = width,
796      .height = height,
797      .depth = psurf->u.tex.last_layer - psurf->u.tex.first_layer + 1
798   };
799
800   /* pipe_color_union and isl_color_value are interchangeable */
801   union isl_color_value *color = (void *) p_color;
802
803   clear_color(ice, psurf->texture, psurf->u.tex.level, &box,
804               render_condition_enabled,
805               isurf->view.format, isurf->view.swizzle, *color);
806}
807
808/**
809 * The pipe->clear_depth_stencil() driver hook.
810 *
811 * This clears the given depth/stencil surface.
812 */
813static void
814crocus_clear_depth_stencil(struct pipe_context *ctx,
815                           struct pipe_surface *psurf,
816                           unsigned flags,
817                           double depth,
818                           unsigned stencil,
819                           unsigned dst_x, unsigned dst_y,
820                           unsigned width, unsigned height,
821                           bool render_condition_enabled)
822{
823   return;
824#if 0
825   struct crocus_context *ice = (void *) ctx;
826   struct pipe_box box = {
827      .x = dst_x,
828      .y = dst_y,
829      .z = psurf->u.tex.first_layer,
830      .width = width,
831      .height = height,
832      .depth = psurf->u.tex.last_layer - psurf->u.tex.first_layer + 1
833   };
834   uint32_t blit_flags = 0;
835
836   assert(util_format_is_depth_or_stencil(psurf->texture->format));
837
838   crocus_blitter_begin(ice, CROCUS_SAVE_FRAGMENT_STATE);
839   util_blitter_clear(ice->blitter, width, height,
840                      1, flags, NULL, depth, stencil, render_condition_enabled);
841#if 0
842   clear_depth_stencil(ice, psurf->texture, psurf->u.tex.level, &box,
843                       render_condition_enabled,
844                       flags & PIPE_CLEAR_DEPTH, flags & PIPE_CLEAR_STENCIL,
845                       depth, stencil);
846#endif
847#endif
848}
849
850void
851crocus_init_clear_functions(struct pipe_context *ctx)
852{
853   ctx->clear = crocus_clear;
854   ctx->clear_texture = crocus_clear_texture;
855   ctx->clear_render_target = crocus_clear_render_target;
856   ctx->clear_depth_stencil = crocus_clear_depth_stencil;
857}
858