~mmach/netext73/mesa-haswell

« back to all changes in this revision

Viewing changes to src/gallium/drivers/softpipe/sp_tile_cache.c

  • Committer: mmach
  • Date: 2022-09-22 19:56:13 UTC
  • Revision ID: netbit73@gmail.com-20220922195613-wtik9mmy20tmor0i
2022-09-22 21:17:09

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/**************************************************************************
2
 
 * 
3
 
 * Copyright 2007 VMware, Inc.
4
 
 * All Rights Reserved.
5
 
 * 
6
 
 * Permission is hereby granted, free of charge, to any person obtaining a
7
 
 * copy of this software and associated documentation files (the
8
 
 * "Software"), to deal in the Software without restriction, including
9
 
 * without limitation the rights to use, copy, modify, merge, publish,
10
 
 * distribute, sub license, and/or sell copies of the Software, and to
11
 
 * permit persons to whom the Software is furnished to do so, subject to
12
 
 * the following conditions:
13
 
 * 
14
 
 * The above copyright notice and this permission notice (including the
15
 
 * next paragraph) shall be included in all copies or substantial portions
16
 
 * of the Software.
17
 
 * 
18
 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19
 
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20
 
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21
 
 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22
 
 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23
 
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24
 
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25
 
 * 
26
 
 **************************************************************************/
27
 
 
28
 
/**
29
 
 * Render target tile caching.
30
 
 *
31
 
 * Author:
32
 
 *    Brian Paul
33
 
 */
34
 
 
35
 
#include "util/u_inlines.h"
36
 
#include "util/format/u_format.h"
37
 
#include "util/u_memory.h"
38
 
#include "util/u_tile.h"
39
 
#include "sp_tile_cache.h"
40
 
 
41
 
static struct softpipe_cached_tile *
42
 
sp_alloc_tile(struct softpipe_tile_cache *tc);
43
 
 
44
 
 
45
 
/**
46
 
 * Return the position in the cache for the tile that contains win pos (x,y).
47
 
 * We currently use a direct mapped cache so this is like a hack key.
48
 
 * At some point we should investigate something more sophisticated, like
49
 
 * a LRU replacement policy.
50
 
 */
51
 
#define CACHE_POS(x, y, l)                        \
52
 
   (((x) + (y) * 5 + (l) * 10) % NUM_ENTRIES)
53
 
 
54
 
 
55
 
static inline int addr_to_clear_pos(union tile_address addr)
56
 
{
57
 
   int pos;
58
 
   pos = addr.bits.layer * (MAX_WIDTH / TILE_SIZE) * (MAX_HEIGHT / TILE_SIZE);
59
 
   pos += addr.bits.y * (MAX_WIDTH / TILE_SIZE);
60
 
   pos += addr.bits.x;
61
 
   return pos;
62
 
}
63
 
/**
64
 
 * Is the tile at (x,y) in cleared state?
65
 
 */
66
 
static inline uint
67
 
is_clear_flag_set(const uint *bitvec, union tile_address addr, unsigned max)
68
 
{
69
 
   int pos, bit;
70
 
   pos = addr_to_clear_pos(addr);
71
 
   assert(pos / 32 < max);
72
 
   bit = bitvec[pos / 32] & (1 << (pos & 31));
73
 
   return bit;
74
 
}
75
 
   
76
 
 
77
 
/**
78
 
 * Mark the tile at (x,y) as not cleared.
79
 
 */
80
 
static inline void
81
 
clear_clear_flag(uint *bitvec, union tile_address addr, unsigned max)
82
 
{
83
 
   int pos;
84
 
   pos = addr_to_clear_pos(addr);
85
 
   assert(pos / 32 < max);
86
 
   bitvec[pos / 32] &= ~(1 << (pos & 31));
87
 
}
88
 
   
89
 
 
90
 
struct softpipe_tile_cache *
91
 
sp_create_tile_cache( struct pipe_context *pipe )
92
 
{
93
 
   struct softpipe_tile_cache *tc;
94
 
   uint pos;
95
 
 
96
 
   /* sanity checking: max sure MAX_WIDTH/HEIGHT >= largest texture image */
97
 
   assert(MAX_WIDTH >= pipe->screen->get_param(pipe->screen,
98
 
                                               PIPE_CAP_MAX_TEXTURE_2D_SIZE));
99
 
 
100
 
   STATIC_ASSERT(sizeof(union tile_address) == 4);
101
 
 
102
 
   STATIC_ASSERT((TILE_SIZE << TILE_ADDR_BITS) >= MAX_WIDTH);
103
 
 
104
 
   tc = CALLOC_STRUCT( softpipe_tile_cache );
105
 
   if (tc) {
106
 
      tc->pipe = pipe;
107
 
      for (pos = 0; pos < ARRAY_SIZE(tc->tile_addrs); pos++) {
108
 
         tc->tile_addrs[pos].bits.invalid = 1;
109
 
      }
110
 
      tc->last_tile_addr.bits.invalid = 1;
111
 
 
112
 
      /* this allocation allows us to guarantee that allocation
113
 
       * failures are never fatal later
114
 
       */
115
 
      tc->tile = MALLOC_STRUCT( softpipe_cached_tile );
116
 
      if (!tc->tile)
117
 
      {
118
 
         FREE(tc);
119
 
         return NULL;
120
 
      }
121
 
 
122
 
      /* XXX this code prevents valgrind warnings about use of uninitialized
123
 
       * memory in programs that don't clear the surface before rendering.
124
 
       * However, it breaks clearing in other situations (such as in
125
 
       * progs/tests/drawbuffers, see bug 24402).
126
 
       */
127
 
#if 0
128
 
      /* set flags to indicate all the tiles are cleared */
129
 
      memset(tc->clear_flags, 255, sizeof(tc->clear_flags));
130
 
#endif
131
 
   }
132
 
   return tc;
133
 
}
134
 
 
135
 
 
136
 
void
137
 
sp_destroy_tile_cache(struct softpipe_tile_cache *tc)
138
 
{
139
 
   if (tc) {
140
 
      uint pos;
141
 
 
142
 
      for (pos = 0; pos < ARRAY_SIZE(tc->entries); pos++) {
143
 
         /*assert(tc->entries[pos].x < 0);*/
144
 
         FREE( tc->entries[pos] );
145
 
      }
146
 
      FREE( tc->tile );
147
 
 
148
 
      if (tc->num_maps) {
149
 
         int i;
150
 
         for (i = 0; i < tc->num_maps; i++)
151
 
            if (tc->transfer[i]) {
152
 
               tc->pipe->texture_unmap(tc->pipe, tc->transfer[i]);
153
 
            }
154
 
         FREE(tc->transfer);
155
 
         FREE(tc->transfer_map);
156
 
         FREE(tc->clear_flags);
157
 
      }
158
 
 
159
 
      FREE( tc );
160
 
   }
161
 
}
162
 
 
163
 
 
164
 
/**
165
 
 * Specify the surface to cache.
166
 
 */
167
 
void
168
 
sp_tile_cache_set_surface(struct softpipe_tile_cache *tc,
169
 
                          struct pipe_surface *ps)
170
 
{
171
 
   struct pipe_context *pipe = tc->pipe;
172
 
   int i;
173
 
 
174
 
   if (tc->num_maps) {
175
 
      if (ps == tc->surface)
176
 
         return;
177
 
 
178
 
      for (i = 0; i < tc->num_maps; i++) {
179
 
         pipe->texture_unmap(pipe, tc->transfer[i]);
180
 
         tc->transfer[i] = NULL;
181
 
         tc->transfer_map[i] = NULL;
182
 
      }
183
 
      FREE(tc->transfer);
184
 
      FREE(tc->transfer_map);
185
 
      tc->num_maps = 0;
186
 
 
187
 
      FREE(tc->clear_flags);
188
 
      tc->clear_flags_size = 0;
189
 
   }
190
 
 
191
 
   tc->surface = ps;
192
 
 
193
 
   if (ps) {
194
 
      tc->num_maps = ps->u.tex.last_layer - ps->u.tex.first_layer + 1;
195
 
      tc->transfer = CALLOC(tc->num_maps, sizeof(struct pipe_transfer *));
196
 
      tc->transfer_map = CALLOC(tc->num_maps, sizeof(void *));
197
 
 
198
 
      tc->clear_flags_size = (MAX_WIDTH / TILE_SIZE) * (MAX_HEIGHT / TILE_SIZE) * tc->num_maps / 32 * sizeof(uint);
199
 
      tc->clear_flags = CALLOC(1, tc->clear_flags_size);
200
 
 
201
 
      if (ps->texture->target != PIPE_BUFFER) {
202
 
         for (i = 0; i < tc->num_maps; i++) {
203
 
            tc->transfer_map[i] = pipe_texture_map(pipe, ps->texture,
204
 
                                                    ps->u.tex.level, ps->u.tex.first_layer + i,
205
 
                                                    PIPE_MAP_READ_WRITE |
206
 
                                                    PIPE_MAP_UNSYNCHRONIZED,
207
 
                                                    0, 0, ps->width, ps->height,
208
 
                                                    &tc->transfer[i]);
209
 
         }
210
 
      }
211
 
      else {
212
 
         /* can't render to buffers */
213
 
         assert(0);
214
 
      }
215
 
 
216
 
      tc->depth_stencil = util_format_is_depth_or_stencil(ps->format);
217
 
   }
218
 
}
219
 
 
220
 
 
221
 
/**
222
 
 * Return the transfer being cached.
223
 
 */
224
 
struct pipe_surface *
225
 
sp_tile_cache_get_surface(struct softpipe_tile_cache *tc)
226
 
{
227
 
   return tc->surface;
228
 
}
229
 
 
230
 
 
231
 
/**
232
 
 * Set pixels in a tile to the given clear color/value, float.
233
 
 */
234
 
static void
235
 
clear_tile_rgba(struct softpipe_cached_tile *tile,
236
 
                enum pipe_format format,
237
 
                const union pipe_color_union *clear_value)
238
 
{
239
 
   if (clear_value->f[0] == 0.0 &&
240
 
       clear_value->f[1] == 0.0 &&
241
 
       clear_value->f[2] == 0.0 &&
242
 
       clear_value->f[3] == 0.0) {
243
 
      memset(tile->data.color, 0, sizeof(tile->data.color));
244
 
   }
245
 
   else {
246
 
      uint i, j;
247
 
 
248
 
      if (util_format_is_pure_uint(format)) {
249
 
         for (i = 0; i < TILE_SIZE; i++) {
250
 
            for (j = 0; j < TILE_SIZE; j++) {
251
 
               tile->data.colorui128[i][j][0] = clear_value->ui[0];
252
 
               tile->data.colorui128[i][j][1] = clear_value->ui[1];
253
 
               tile->data.colorui128[i][j][2] = clear_value->ui[2];
254
 
               tile->data.colorui128[i][j][3] = clear_value->ui[3];
255
 
            }
256
 
         }
257
 
      } else if (util_format_is_pure_sint(format)) {
258
 
         for (i = 0; i < TILE_SIZE; i++) {
259
 
            for (j = 0; j < TILE_SIZE; j++) {
260
 
               tile->data.colori128[i][j][0] = clear_value->i[0];
261
 
               tile->data.colori128[i][j][1] = clear_value->i[1];
262
 
               tile->data.colori128[i][j][2] = clear_value->i[2];
263
 
               tile->data.colori128[i][j][3] = clear_value->i[3];
264
 
            }
265
 
         }
266
 
      } else {
267
 
         for (i = 0; i < TILE_SIZE; i++) {
268
 
            for (j = 0; j < TILE_SIZE; j++) {
269
 
               tile->data.color[i][j][0] = clear_value->f[0];
270
 
               tile->data.color[i][j][1] = clear_value->f[1];
271
 
               tile->data.color[i][j][2] = clear_value->f[2];
272
 
               tile->data.color[i][j][3] = clear_value->f[3];
273
 
            }
274
 
         }
275
 
      }
276
 
   }
277
 
}
278
 
 
279
 
 
280
 
/**
281
 
 * Set a tile to a solid value/color.
282
 
 */
283
 
static void
284
 
clear_tile(struct softpipe_cached_tile *tile,
285
 
           enum pipe_format format,
286
 
           uint64_t clear_value)
287
 
{
288
 
   uint i, j;
289
 
 
290
 
   switch (util_format_get_blocksize(format)) {
291
 
   case 1:
292
 
      memset(tile->data.any, (int) clear_value, TILE_SIZE * TILE_SIZE);
293
 
      break;
294
 
   case 2:
295
 
      if (clear_value == 0) {
296
 
         memset(tile->data.any, 0, 2 * TILE_SIZE * TILE_SIZE);
297
 
      }
298
 
      else {
299
 
         for (i = 0; i < TILE_SIZE; i++) {
300
 
            for (j = 0; j < TILE_SIZE; j++) {
301
 
               tile->data.depth16[i][j] = (ushort) clear_value;
302
 
            }
303
 
         }
304
 
      }
305
 
      break;
306
 
   case 4:
307
 
      if (clear_value == 0) {
308
 
         memset(tile->data.any, 0, 4 * TILE_SIZE * TILE_SIZE);
309
 
      }
310
 
      else {
311
 
         for (i = 0; i < TILE_SIZE; i++) {
312
 
            for (j = 0; j < TILE_SIZE; j++) {
313
 
               tile->data.depth32[i][j] = (uint) clear_value;
314
 
            }
315
 
         }
316
 
      }
317
 
      break;
318
 
   case 8:
319
 
      if (clear_value == 0) {
320
 
         memset(tile->data.any, 0, 8 * TILE_SIZE * TILE_SIZE);
321
 
      }
322
 
      else {
323
 
         for (i = 0; i < TILE_SIZE; i++) {
324
 
            for (j = 0; j < TILE_SIZE; j++) {
325
 
               tile->data.depth64[i][j] = clear_value;
326
 
            }
327
 
         }
328
 
      }
329
 
      break;
330
 
   default:
331
 
      assert(0);
332
 
   }
333
 
}
334
 
 
335
 
 
336
 
/**
337
 
 * Actually clear the tiles which were flagged as being in a clear state.
338
 
 */
339
 
static void
340
 
sp_tile_cache_flush_clear(struct softpipe_tile_cache *tc, int layer)
341
 
{
342
 
   struct pipe_transfer *pt = tc->transfer[layer];
343
 
   const uint w = tc->transfer[layer]->box.width;
344
 
   const uint h = tc->transfer[layer]->box.height;
345
 
   uint x, y;
346
 
   uint numCleared = 0;
347
 
 
348
 
   assert(pt->resource);
349
 
 
350
 
   /* clear the scratch tile to the clear value */
351
 
   if (tc->depth_stencil) {
352
 
      clear_tile(tc->tile, pt->resource->format, tc->clear_val);
353
 
   } else {
354
 
      clear_tile_rgba(tc->tile, pt->resource->format, &tc->clear_color);
355
 
   }
356
 
 
357
 
   /* push the tile to all positions marked as clear */
358
 
   for (y = 0; y < h; y += TILE_SIZE) {
359
 
      for (x = 0; x < w; x += TILE_SIZE) {
360
 
         union tile_address addr = tile_address(x, y, layer);
361
 
 
362
 
         if (is_clear_flag_set(tc->clear_flags, addr, tc->clear_flags_size)) {
363
 
            /* write the scratch tile to the surface */
364
 
            if (tc->depth_stencil) {
365
 
               pipe_put_tile_raw(pt, tc->transfer_map[layer],
366
 
                                 x, y, TILE_SIZE, TILE_SIZE,
367
 
                                 tc->tile->data.any, 0/*STRIDE*/);
368
 
            }
369
 
            else {
370
 
               pipe_put_tile_rgba(pt, tc->transfer_map[layer],
371
 
                                  x, y, TILE_SIZE, TILE_SIZE,
372
 
                                  tc->surface->format,
373
 
                                  tc->tile->data.color);
374
 
            }
375
 
            numCleared++;
376
 
         }
377
 
      }
378
 
   }
379
 
 
380
 
 
381
 
#if 0
382
 
   debug_printf("num cleared: %u\n", numCleared);
383
 
#endif
384
 
}
385
 
 
386
 
static void
387
 
sp_flush_tile(struct softpipe_tile_cache* tc, unsigned pos)
388
 
{
389
 
   int layer = tc->tile_addrs[pos].bits.layer;
390
 
   if (!tc->tile_addrs[pos].bits.invalid) {
391
 
      if (tc->depth_stencil) {
392
 
         pipe_put_tile_raw(tc->transfer[layer], tc->transfer_map[layer],
393
 
                           tc->tile_addrs[pos].bits.x * TILE_SIZE,
394
 
                           tc->tile_addrs[pos].bits.y * TILE_SIZE,
395
 
                           TILE_SIZE, TILE_SIZE,
396
 
                           tc->entries[pos]->data.depth32, 0/*STRIDE*/);
397
 
      }
398
 
      else {
399
 
         pipe_put_tile_rgba(tc->transfer[layer], tc->transfer_map[layer],
400
 
                            tc->tile_addrs[pos].bits.x * TILE_SIZE,
401
 
                            tc->tile_addrs[pos].bits.y * TILE_SIZE,
402
 
                            TILE_SIZE, TILE_SIZE,
403
 
                            tc->surface->format,
404
 
                            tc->entries[pos]->data.color);
405
 
      }
406
 
      tc->tile_addrs[pos].bits.invalid = 1;  /* mark as empty */
407
 
   }
408
 
}
409
 
 
410
 
/**
411
 
 * Flush the tile cache: write all dirty tiles back to the transfer.
412
 
 * any tiles "flagged" as cleared will be "really" cleared.
413
 
 */
414
 
void
415
 
sp_flush_tile_cache(struct softpipe_tile_cache *tc)
416
 
{
417
 
   int inuse = 0, pos;
418
 
   int i;
419
 
   if (tc->num_maps) {
420
 
      /* caching a drawing transfer */
421
 
      for (pos = 0; pos < ARRAY_SIZE(tc->entries); pos++) {
422
 
         struct softpipe_cached_tile *tile = tc->entries[pos];
423
 
         if (!tile)
424
 
         {
425
 
            assert(tc->tile_addrs[pos].bits.invalid);
426
 
            continue;
427
 
         }
428
 
         sp_flush_tile(tc, pos);
429
 
         ++inuse;
430
 
      }
431
 
 
432
 
      if (!tc->tile)
433
 
         tc->tile = sp_alloc_tile(tc);
434
 
 
435
 
      for (i = 0; i < tc->num_maps; i++)
436
 
         sp_tile_cache_flush_clear(tc, i);
437
 
      /* reset all clear flags to zero */
438
 
      memset(tc->clear_flags, 0, tc->clear_flags_size);
439
 
 
440
 
      tc->last_tile_addr.bits.invalid = 1;
441
 
   }
442
 
 
443
 
#if 0
444
 
   debug_printf("flushed tiles in use: %d\n", inuse);
445
 
#endif
446
 
}
447
 
 
448
 
static struct softpipe_cached_tile *
449
 
sp_alloc_tile(struct softpipe_tile_cache *tc)
450
 
{
451
 
   struct softpipe_cached_tile * tile = MALLOC_STRUCT(softpipe_cached_tile);
452
 
   if (!tile)
453
 
   {
454
 
      /* in this case, steal an existing tile */
455
 
      if (!tc->tile)
456
 
      {
457
 
         unsigned pos;
458
 
         for (pos = 0; pos < ARRAY_SIZE(tc->entries); ++pos) {
459
 
            if (!tc->entries[pos])
460
 
               continue;
461
 
 
462
 
            sp_flush_tile(tc, pos);
463
 
            tc->tile = tc->entries[pos];
464
 
            tc->entries[pos] = NULL;
465
 
            break;
466
 
         }
467
 
 
468
 
         /* this should never happen */
469
 
         if (!tc->tile)
470
 
            abort();
471
 
      }
472
 
 
473
 
      tile = tc->tile;
474
 
      tc->tile = NULL;
475
 
 
476
 
      tc->last_tile_addr.bits.invalid = 1;
477
 
   }
478
 
   return tile;
479
 
}
480
 
 
481
 
/**
482
 
 * Get a tile from the cache.
483
 
 * \param x, y  position of tile, in pixels
484
 
 */
485
 
struct softpipe_cached_tile *
486
 
sp_find_cached_tile(struct softpipe_tile_cache *tc, 
487
 
                    union tile_address addr )
488
 
{
489
 
   struct pipe_transfer *pt;
490
 
   /* cache pos/entry: */
491
 
   const int pos = CACHE_POS(addr.bits.x,
492
 
                             addr.bits.y, addr.bits.layer);
493
 
   struct softpipe_cached_tile *tile = tc->entries[pos];
494
 
   int layer;
495
 
   if (!tile) {
496
 
      tile = sp_alloc_tile(tc);
497
 
      tc->entries[pos] = tile;
498
 
   }
499
 
 
500
 
   if (addr.value != tc->tile_addrs[pos].value) {
501
 
 
502
 
      layer = tc->tile_addrs[pos].bits.layer;
503
 
      if (tc->tile_addrs[pos].bits.invalid == 0) {
504
 
         /* put dirty tile back in framebuffer */
505
 
         if (tc->depth_stencil) {
506
 
            pipe_put_tile_raw(tc->transfer[layer], tc->transfer_map[layer],
507
 
                              tc->tile_addrs[pos].bits.x * TILE_SIZE,
508
 
                              tc->tile_addrs[pos].bits.y * TILE_SIZE,
509
 
                              TILE_SIZE, TILE_SIZE,
510
 
                              tile->data.depth32, 0/*STRIDE*/);
511
 
         }
512
 
         else {
513
 
            pipe_put_tile_rgba(tc->transfer[layer], tc->transfer_map[layer],
514
 
                               tc->tile_addrs[pos].bits.x * TILE_SIZE,
515
 
                               tc->tile_addrs[pos].bits.y * TILE_SIZE,
516
 
                               TILE_SIZE, TILE_SIZE,
517
 
                               tc->surface->format,
518
 
                               tile->data.color);
519
 
         }
520
 
      }
521
 
 
522
 
      tc->tile_addrs[pos] = addr;
523
 
 
524
 
      layer = tc->tile_addrs[pos].bits.layer;
525
 
      pt = tc->transfer[layer];
526
 
      assert(pt->resource);
527
 
 
528
 
      if (is_clear_flag_set(tc->clear_flags, addr, tc->clear_flags_size)) {
529
 
         /* don't get tile from framebuffer, just clear it */
530
 
         if (tc->depth_stencil) {
531
 
            clear_tile(tile, pt->resource->format, tc->clear_val);
532
 
         }
533
 
         else {
534
 
            clear_tile_rgba(tile, pt->resource->format, &tc->clear_color);
535
 
         }
536
 
         clear_clear_flag(tc->clear_flags, addr, tc->clear_flags_size);
537
 
      }
538
 
      else {
539
 
         /* get new tile data from transfer */
540
 
         if (tc->depth_stencil) {
541
 
            pipe_get_tile_raw(tc->transfer[layer], tc->transfer_map[layer],
542
 
                              tc->tile_addrs[pos].bits.x * TILE_SIZE,
543
 
                              tc->tile_addrs[pos].bits.y * TILE_SIZE,
544
 
                              TILE_SIZE, TILE_SIZE,
545
 
                              tile->data.depth32, 0/*STRIDE*/);
546
 
         }
547
 
         else {
548
 
            pipe_get_tile_rgba(tc->transfer[layer], tc->transfer_map[layer],
549
 
                               tc->tile_addrs[pos].bits.x * TILE_SIZE,
550
 
                               tc->tile_addrs[pos].bits.y * TILE_SIZE,
551
 
                               TILE_SIZE, TILE_SIZE,
552
 
                               tc->surface->format,
553
 
                               tile->data.color);
554
 
         }
555
 
      }
556
 
   }
557
 
 
558
 
   tc->last_tile = tile;
559
 
   tc->last_tile_addr = addr;
560
 
   return tile;
561
 
}
562
 
 
563
 
 
564
 
 
565
 
 
566
 
 
567
 
/**
568
 
 * When a whole surface is being cleared to a value we can avoid
569
 
 * fetching tiles above.
570
 
 * Save the color and set a 'clearflag' for each tile of the screen.
571
 
 */
572
 
void
573
 
sp_tile_cache_clear(struct softpipe_tile_cache *tc,
574
 
                    const union pipe_color_union *color,
575
 
                    uint64_t clearValue)
576
 
{
577
 
   uint pos;
578
 
 
579
 
   tc->clear_color = *color;
580
 
 
581
 
   tc->clear_val = clearValue;
582
 
 
583
 
   /* set flags to indicate all the tiles are cleared */
584
 
   memset(tc->clear_flags, 255, tc->clear_flags_size);
585
 
 
586
 
   for (pos = 0; pos < ARRAY_SIZE(tc->tile_addrs); pos++) {
587
 
      tc->tile_addrs[pos].bits.invalid = 1;
588
 
   }
589
 
   tc->last_tile_addr.bits.invalid = 1;
590
 
}